jvm基础学习总结笔记

jvm基础学习总结笔记_第1张图片

其中内存模型 , 类加载机制 ,GC 是重点方面 . 性能调优部分更偏向应用 , 重点突出实践能力 . 编译器优化
和执行模式部分偏向于理论基础 , 重点掌握知识点 .
需了解 内存模型 各部分作用 , 保存哪些数据 .
类加载 双亲委派加载机制 , 常用加载器分别加载哪种类型的类 .
GC 分代回收的思想和依据以及不同垃圾回收算法的回收思路和适合场景 .
性能调优 常有 JVM 优化参数作用 , 参数调优的依据 , 常用的 JVM 分析工具能分析哪些问题以及使用方法 .
执行模式 解释 / 编译 / 混合模式的优缺点 ,Java7 提供的分层编译技术 ,JIT 即时编译技术 ,OSR 栈上替
,C1/C2 编译器针对的场景 ,C2 针对的是 server 模式 , 优化更激进 . 新技术方面 Java10 graal 编译器
编译器优化 j avac 的编译过程 ,ast 抽象语法树 , 编译器优化和运行器优化 .
2 、知识点详解:
1 JVM 内存模型
线程独占 : , 本地方法栈 , 程序计数器 线程共享 : , 方法区
2 、栈:
又称方法栈 , 线程私有的 , 线程执行方法是都会创建一个栈阵 , 用来存储局部变量表 , 操作栈 , 动态链接 , 方法出口等信息. 调用方法时执行入栈 , 方法返回式执行出栈 .
3 、本地方法栈
与栈类似 , 也是用来保存执行方法的信息 . 执行 Java 方法是使用栈 , 执行 Native 方法时使用本地方法栈 .
4 、程序计数器
保存着当前线程执行的字节码位置 , 每个线程工作时都有独立的计数器 , 只为执行 Java 方法服务 , 执行
Native 方法时 , 程序计数器为空 .
5 、堆
JVM 内存管理最大的一块 , 对被线程共享 , 目的是存放对象的实例 , 几乎所欲的对象实例都会放在这里 ,
当堆没有可用空间时 , 会抛出 OOM 异常 . 根据对象的存活周期不同 ,JVM 把对象进行分代管理 , 由垃圾回 收器进行垃圾的回收管理
6 、方法区:
又称非堆区 , 用于存储已被虚拟机加载的类信息 , 常量 , 静态变量 , 即时编译器优化后的代码等数据 .1.7
的永久代和 1.8 的元空间都是方法区的一种实现
JMM 是定义程序中变量的访问规则 , 线程对于变量的操作只能在自己的工作内存中进行 , 而不能直接对主内存操作. 由于指令重排序 , 读写的顺序会被打乱 , 因此 JMM 需要提供原子性 , 可见性 , 有序性保证 .

jvm基础学习总结笔记_第2张图片

 

其中 验证 , 准备 , 解析 合称链接
加载 通过类的完全限定名 , 查找此类字节码文件 , 利用字节码文件创建 Class 对象 .
验证 确保 Class 文件符合当前虚拟机的要求 , 不会危害到虚拟机自身安全 .
准备 进行内存分配 , static 修饰的类变量分配内存 , 并设置初始值 (0 null). 不包含 fifinal 修饰的静态变
, 因为 fifinal 变量在编译时分配 .
解析 将常量池中的符号引用替换为直接引用的过程 . 直接引用为直接指向目标的指针或者相对偏移量
.
初始化 主要完成静态块执行以及静态变量的赋值 . 先初始化父类 , 再初始化当前类 . 只有对类主动使用
时才会初始化 .
触发条件包括 , 创建类的实例时 , 访问类的静态方法或静态变量的时候 , 使用 Class.forName 反射类的时
, 或者某个子类初始化的时候 .
Java 自带的加载器加载的类 , 在虚拟机的生命周期中是不会被卸载的 , 只有用户自定义的加载器加载的
类才可以被卸 .

jvm基础学习总结笔记_第3张图片

双亲委派模式 , 即加载器加载类时先把请求委托给自己的父类加载器执行 , 直到顶层的启动类加载器 .
父类加载器能够完成加载则成功返回 , 不能则子类加载器才自己尝试加载 .*
优点 :
1. 避免类的重复加载
2. 避免 Java 的核心 API 被篡改

jvm基础学习总结笔记_第4张图片 

 

G1 算法
1.9 后默认的垃圾回收算法 , 特点保持高回收率的同时减少停顿 . 采用每次只清理一部分 , 而不是清理全
部的增量式清理 , 以保证停顿时间不会过长
其取消了年轻代与老年代的物理划分 , 但仍属于分代收集器 , 算法将堆分为若干个逻辑区域 (region),
部分用作年轻代 , 一部分用作老年代 , 还有用来存储巨型对象的分区 .
CMS 相同 , 会遍历所有对象 , 标记引用情况 , 清除对象后会对区域进行复制移动 , 以整合碎片空间 .
年轻代回收 : 并行复制采用复制算法 , 并行收集 , StopTheWorld.
老年代回收 : 会对年轻代一并回收
初始标记完成堆 root 对象的标记 , StopTheWorld. 并发标记 GC 线程和应用线程并发执行 . 最终标记
完成三色标记周期 , StopTheWorld. 复制 / 清楚会优先对可回收空间加大的区域进行回收
b ZGC 算法
前面提供的高效垃圾回收算法 , 针对大堆内存设计 , 可以处理 TB 级别的堆 , 可以做到 10ms 以下的回收停顿时间.

jvm基础学习总结笔记_第5张图片

jvm基础学习总结笔记_第6张图片

jvm基础学习总结笔记_第7张图片

 jvm基础学习总结笔记_第8张图片

5 、说说堆和栈的区别
栈是运行时单位,代表着逻辑,内含基本数据类型和堆中对象引用,所在区域连续,没有碎片;堆
是存储单位,代表着数据,可被多个栈共享(包括成员中基本数据类型、引用和引用对象),所在
区域不连续,会有碎片。
1 、功能不同
栈内存用来存储局部变量和方法调用,而堆内存用来存储 Java 中的对象。无论是成员变量,局部变
量,还是类变量,它们指向的对象都存储在堆内存中。
2 、共享性不同
栈内存是线程私有的。 堆内存是所有线程共有的。
3 、异常错误不同
如果栈内存或者堆内存不足都会抛出异常。 栈空间不足: java.lang.StackOverFlowError 。 堆空间
不足: java.lang.OutOfMemoryError
4 、空间大小
栈的空间大小远远小于堆的。
什么时候会触发 FullGC
除直接调用 System.gc 外,触发 Full GC 执行的情况有如下四种。
1. 旧生代空间不足 旧生代空间只有 在新生代对象转入及创建为大对象、大数组时才会出现不足的现象,当执行Full GC 后空间仍然不足,则抛出如下错误: java.lang.OutOfMemoryError: Java heap space 为避免以上两种状况引起 的FullGC ,调优时应尽量做到让对象在 Minor GC 阶段被回收、让对象在新生代多存活一段时间及不 要创建过大的对象及数组。
2. Permanet Generation 空间满 PermanetGeneration 中存放的为一些 class 的信息等,当系统中
要加载的类、反射的类和调用的方法较多时, Permanet Generation 可能会被占满,在未配置为采
CMS GC 的情况下会执行 Full GC 。如果经过 Full GC 仍然回收不了,那么 JVM 会抛出如下错误信
息: java.lang.OutOfMemoryError: PermGen space 为避免 Perm Gen 占满造成 Full GC 现象,可
采用的方法为增大 Perm Gen 空间或转为使用 CMS GC 仅供阿里
巴巴面试官参考
3. CMS GC 时出现 promotion failed concurrent mode failure 对于采用 CMS 进行旧生代 GC
程序而言,尤其要注意 GC 日志中是否有 promotion failed concurrent mode failure 两种状况,当
这两种状况出现时可能会触发 Full GC promotionfailed 是在进行 Minor GC 时, survivor space
不下、对象只能放入旧生代,而此时旧生代也放不下造成的; concurrent mode failure 是在执行
CMS GC 的过程中同时有对象要放入旧生代,而此时旧生代空间不足造成的。 应对措施为:增大
survivorspace 、旧生代空间或调低触发并发 GC 的比率,但在 JDK 5.0+ 6.0+ 的版本中有可能会由
JDK bug29 导致 CMS remark 完毕后很久才触发 sweeping 动作。对于这种状况,可通过设置 -
XX:CMSMaxAbortablePrecleanTime=5 (单位为 ms )来避免。
4. 统计得到的 Minor GC 晋升到旧生代的平均大小大于旧生代的剩余空间 这是一个较为复杂的触发
情况, Hotspot 为了避免由于新生代对象晋升到旧生代导致旧生代空间不足的现象,在进行 Minor
GC 时,做了一个判断,如果之前统计所得到的 Minor GC 晋升到旧生代的平均大小大于旧生代的剩
余空间,那么就直接触发 Full GC 。 例如程序第一次触发 MinorGC 后,有 6MB 的对象晋升到旧生
代,那么当下一次 Minor GC 发生时,首先检查旧生代的剩余空间是否大于 6MB ,如果小于 6MB
则执行 Full GC 。 当新生代采用 PSGC 时,方式稍有不同, PS GC 是在 Minor GC 后也会检查,例如上 面的例子中第一次Minor GC 后, PS GC 会检查此时旧生代的剩余空间是否大于 6MB ,如小于,则触 发对旧生代的回收。 除了以上4 种状况外,对于使用 RMI 来进行 RPC 或管理的 Sun JDK 应用而言,默认情况下会一小时执行一次Full GC 。可通过在启动时通过 - java
Dsun.rmi.dgc.client.gcInterval=3600000 来设置 Full GC 执行的间隔时间或通过 -XX:+
DisableExplicitGC 来禁止 RMI 调用 System.gc
说说对象分配规则
对象优先分配在 Eden 区,如果 Eden 区没有足够的空间时,虚拟机执行一次 Minor GC
大对象直接进入老年代(大对象是指需要大量连续内存空间的对象)。这样做的目的是避免在
Eden 区和两个 Survivor 区之间发生大量的内存拷贝(新生代采用复制算法收集内存)。
长期存活的对象进入老年代。虚拟机为每个对象定义了一个年龄计数器,如果对象经过了 1
Minor GC 那么对象会进入 Survivor 区,之后每经过一次 Minor GC 那么对象的年龄加 1 ,知道达
到阀值对象进入老年区。
动态判断对象的年龄。如果 Survivor 区中相同年龄的所有对象大小的总和大于 Survivor 空间的
一半,年龄大于或等于该年龄的对象可以直接进入老年代。
空间分配担保。每次进行 Minor GC 时, JVM 会计算 Survivor 区移至老年区的对象的平均大小,
如果这个值大于老年区的剩余值大小则进行一次 Full GC ,如果小于检查
HandlePromotionFailure 设置,如果 true 则只进行 Monitor GC, 如果 false 则进行 Full GC
加载,查找并加载类的二进制数据,在 Java 堆中也创建一个 java.lang.Class 类的对象
连接,连接又包含三块内容:验证、准备、初始化。 1 )验证,文件格式、元数据、字节码、
符号引用验证; 2 )准备,为类的静态变量分配内存,并将其初始化为默认值; 3 )解析,把
类中的符号引用转换为直接引用
初始化,为类的静态变量赋予正确的初始值
使用, new 出对象程序中使用
卸载,执行垃圾回收
如何判断对象可以被回收?
判断对象是否存活一般有两种方式:
引用计数:每个对象有一个引用计数属性,新增一个引用时计数加 1 ,引用释放时计数减 1 ,计
数为 0 时可以回收。此方法简单,无法解决对象相互循环引用的问题。
可达性分析( Reachability Analysis ):从 GC Roots 开始向下搜索,搜索所走过的路径称为引
用链。当一个对象到 GC Roots 没有任何引用链相连时,则证明此对象是不可用的,不可达对
象。
15 JVM 的永久代中会发生垃圾回收么?
垃圾回收不会发生在永久代,如果永久代满了或者是超过了临界值,会触发完全垃圾回收 (Full
GC) 。如果你仔细查看垃圾收集器的输出信息,就会发现永久代也是被回收的。这就是为什么正确
的永久代大小对避免 Full GC 是非常重要的原因。请参考下 Java8 :从永久代到元数据区 ( 注: Java8 中已经移除了永久代,新加了一个叫做元数据区的native 内存区 )
你知道哪些垃圾收集算法
GC 最基础的算法有三种: 标记 - 清除算法、复制算法、标记 - 压缩算法,我们常用的垃圾回收器一般都采用分代收集算法。
标记 - 清除算法, 标记 - 清除 Mark-Sweep )算法,如它的名字一样,算法分为 标记
两个阶段:首先标记出所有需要回收的对象,在标记完成后统一回收掉所有被标记的对象。
复制算法, 复制 Copying )的收集算法,它将可用内存按容量划分为大小相等的两块,每次
只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后
再把已使用过的内存空间一次清理掉。
标记 - 压缩算法,标记过程仍然与 标记 - 清除 算法一样,但后续步骤不是直接对可回收对象进行
清理,而是让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存
分代收集算法, 分代收集 Generational Collection )算法,把 Java 堆分为新生代和老年代,
这样就可以根据各个年代的特点采用最适当的收集算法。
 
17、调优命令有哪些?
Sun JDK监控和故障处理命令有jps jstat jmap jhat jstack jinfo
jps,JVM Process Status Tool,显示指定系统内所有的HotSpot虚拟机进程。
jstat,JVM statistics Monitoring是用于监视虚拟机运行时状态信息的命令,它可以显示出虚拟
机进程中的类装载、内存、垃圾收集、JIT编译等运行数据。
jmap,JVM Memory Map命令用于生成heap dump文件
jhat,JVM Heap Analysis Tool命令是与jmap搭配使用,用来分析jmap生成的dump,jhat内
置了一个微型的HTTP/HTML服务器,生成dump的分析结果后,可以在浏览器中查看
jstack,用于生成java虚拟机当前时刻的线程快照。
jinfo,JVM Confifiguration info 这个命令作用是实时查看和调整虚拟机运行参
常见调优工具有哪些
常用调优工具分为两类 ,jdk 自带监控工具: jconsole jvisualvm ,第三方有: MAT(Memory
Analyzer Tool) GChisto
jconsole Java Monitoring and Management Console 是从 java5 开始,在 JDK 中自带的 java
控和管理控制台,用于对 JVM 中内存,线程和类等的监控
jvisualvm jdk 自带全能工具,可以分析内存快照、线程快照;监控内存变化、 GC 变化等。
MAT Memory Analyzer Tool ,一个基于 Eclipse 的内存分析工具,是一个快速、功能丰富的
Java heap 分析工具,它可以帮助我们查找内存泄漏和减少内存消耗
GChisto ,一款专业分析 gc 日志的工具

你知道哪些 JVM 性能调优参数?
设定堆内存大小
-Xmx :堆内存最大限制。
设定新生代大小。 新生代不宜太小,否则会有大量对象涌入老年代
-XX:NewSize :新生代大小
-XX:NewRatio 新生代和老生代占比
-XX:SurvivorRatio :伊甸园空间和幸存者空间的占比
设定垃圾回收器 年轻代用 -XX:+UseParNewGC 年老代用 -XX:+UseConcMarkSweepGC
对象一定分配在堆中吗?有没有了解逃逸分析技术?
「对象一定分配在堆中吗?」 不一定的, JVM 通过 「逃逸分析」 ,那些逃不出方法的对象会在栈上分配。
「什么是逃逸分析?」
逃逸分析 (Escape Analysis) ,是一种可以有效减少 Java 程序中同步负载和内存堆分配压力的跨函数全局数据流分析算法。通过逃逸分析,Java Hotspot 编译器能够分析出一个新的对象的引用的使用范围,从而决定是否要将这个对象分配到堆上。
逃逸分析 是指分析指针动态范围的方法,它同编译器优化原理的指针分析和外形分析相关联。当变
量(或者对象)在方法中分配后,其指针有可能被返回或者被全局引用,这样就会被其他方法或者
线程所引用,这种现象称作指针(或者引用)的逃逸 (Escape) 。通俗点讲,如果一个对象的指针被
多个方法或者线程引用时,那么我们就称这个对象的指针发生了逃逸。
「逃逸分析的好处」
栈上分配,可以降低垃圾收集器运行的频率。
同步消除,如果发现某个对象只能从一个线程可访问,那么在这个对象上的操作可以不需要同
步。
标量替换,把对象分解成一个个基本类型,并且内存分配不再是分配在堆上,而是分配在栈
上。这样的好处有,一、减少内存使用,因为不用生成对象头。二、程序内存回收效率高,并
GC 频率也会减少。

jvm基础学习总结笔记_第9张图片 

方法区和堆一样,是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、
静态变量、即时编译后的代码等数据。
「什么是永久代?它和方法区有什么关系呢?」
如果在 HotSpot 虚拟机上开发、部署,很多程序员都把方法区称作永久代。可以说方法区是规
范,永久代是 Hotspot 针对该规范进行的实现。在 Java7 及以前的版本,方法区都是永久代实现
的。
「什么是元空间?它和方法区有什么关系呢?」
对于 Java8 HotSpots 取消了永久代,取而代之的是元空间 (Metaspace) 。换句话说,就是方
法区还是在的,只是实现变了,从永久代变为元空间了。
「为什么使用元空间替换了永久代?」
永久代的方法区,和堆使用的物理内存是连续的。

jvm基础学习总结笔记_第10张图片

「永久代」 是通过以下这两个参数配置大小的 ~
-XX:PremSize :设置永久代的初始大小
-XX:MaxPermSize: 设置永久代的最大值,默认是 64M
对于 「永久代」 ,如果动态生成很多 class 的话,就很可能出现 java.lang.OutOfMemoryError:
PermGen space 错误」 ,因为永久代空间配置有限嘛。最典型的场景是,在 web 开发比较多 jsp
面的时候。
JDK8 之后,方法区存在于元空间 (Metaspace) 。物理内存不再与堆连续,而是直接存在于本地
内存中,理论上机器

可以通过以下的参数来设置元空间的大小:
-XX:MetaspaceSize ,初始空间大小,达到该值就会触发垃圾收集进行类型卸载,同时 GC
会对该值进行调整:如果释放了大量的空间,就适当降低该值;如果释放了很少的空间,
那么在不超过 MaxMetaspaceSize 时,适当提高该值。
-XX:MaxMetaspaceSize ,最大空间,默认是没有限制的。
-XX:MinMetaspaceFreeRatio ,在 GC 之后,最小的 Metaspace 剩余空间容量的百分比,
减少为分配空间所导致的垃圾收集
-XX:MaxMetaspaceFreeRatio ,在 GC 之后,最大的 Metaspace 剩余空间容量的百分比,
减少为释放空间所导致的垃圾收集
「所以,为什么使用元空间替换永久代?」
表面上看是为了避免OOM异常。因为通常使用PermSize和MaxPermSize设置永久代的大小就
决定了永久代的上限,但是不是总能知道应该设置为多大合适, 如果使用默认值很容易遇到
OOM错误。当使用元空间时,可以加载多少类的元数据就不再由MaxPermSize控制, 而由系统
的实际可用空间来控制啦

什么是Stop The World ? 什么是OopMap?什么是安全点?

进行垃圾回收的过程中,会涉及对象的移动。为了保证对象引用更新的正确性,必须暂停所有的用
户线程,像这样的停顿,虚拟机设计者形象描述为 Stop The World 。也简称为 STW
HotSpot 中,有个数据结构(映射表)称为 OopMap 。一旦类加载动作完成的时候,
HotSpot 就会把对象内什么偏移量上是什么类型的数据计算出来,记录到 OopMap 。在即时编译过
程中,也会在 「特定的位置」 生成 OopMap ,记录下栈上和寄存器里哪些位置是引用。
这些特定的位置主要在:
1. 循环的末尾(非 counted 循环)
2. 方法临返回前 / 调用方法的 call 指令后
3. 可能抛异常的位置
这些位置就叫作 「安全点 (safepoint) 。」 用户程序执行时并非在代码指令流的任意位置都能够在
停顿下来开始垃圾收集,而是必须是执行到安全点才能够暂停

什么是指针碰撞?
一般情况下, JVM 的对象都放在堆内存中(发生逃逸分析除外)。当类加载检查通过后, Java 虚拟
机开始为新生对象分配内存。如果 Java 堆中内存是绝对规整的,所有被使用过的的内存都被放到一
边,空闲的内存放到另外一边,中间放着一个指针作为分界点的指示器,所分配内存仅仅是把那个
指针向空闲空间方向挪动一段与对象大小相等的实例,这种分配方式就是 指针碰撞。

什么是空闲列表?

如果Java堆内存中的内存并不是规整的,已被使用的内存和空闲的内存相互交错在一起,不可以进

行指针碰撞啦,虚拟机必须维护一个列表,记录哪些内存是可用的,在分配的时候从列表找到一块
大的空间分配给对象实例,并更新列表上的记录,这种分配方式就是空闲列表。
27 ,什么是 TLAB
可以把内存分配的动作按照线程划分在不同的空间之中进行,每个线程在 Java 堆中预先分配一小块
内存 , 这就是 TLAB Thread Local Allocation Buffffer ,本地线程分配缓存) 。虚拟机通过 -
XX:UseTLAB 设定它的。

你知道哪些 JVM 调优参数?
「堆栈内存相关」
-Xms 设置初始堆的大小
-Xmx 设置最大堆的大小
-Xmn 设置年轻代大小,相当于同时配置 -XX:NewSize -XX:MaxNewSize 为一样的值
-Xss 每个线程的堆栈大小
-XX:NewSize 设置年轻代大小 (for 1.3/1.4)
-XX:MaxNewSize 年轻代最大值 (for 1.3/1.4)
-XX:NewRatio 年轻代与年老代的比值 ( 除去持久代 )
-XX:SurvivorRatio Eden 区与 Survivor 区的的比值
-XX:PretenureSizeThreshold 当创建的对象超过指定大小时,直接把对象分配在老年代。
-XX:MaxTenuringThreshold 设定对象在 Survivor 复制的最大年龄阈值,超过阈值转移到
老年代
「垃圾收集器相关」
-XX:+UseParallelGC :选择垃圾收集器为并行收集器。
-XX:ParallelGCThreads=20 :配置并行收集器的线程数
-XX:+UseConcMarkSweepGC :设置年老代为并发收集。
-XX:CMSFullGCsBeforeCompaction=5 由于并发收集器不对内存空间进行压缩、整理,
所以运行一段时间以后会产生 碎片 ,使得运行效率降低。此值设置运行 5 GC 以后对内
存空间进行压缩、整理。
-XX:+UseCMSCompactAtFullCollection :打开对年老代的压缩。可能会影响性能,但是
可以消除碎片
「辅助信息相关」
-XX:+PrintGCDetails 打印 GC 详细信息
-XX:+HeapDumpOnOutOfMemoryError JVM 在发生内存溢出的时候自动生成内存快照 ,
排查问题用
-XX:+DisableExplicitGC 禁止系统 System.gc() ,防止手动误触发 FGC 造成问题 .
-XX:+PrintTLAB 查看 TLAB 空间的使用情况
Serial 收集器(复制算法 ): 新生代单线程收集器,标记和清理都是单线程,优点是简单高效;
ParNew 收集器 ( 复制算法 ): 新生代收并行集器,实际上是 Serial 收集器的多线程版本,在多核
CPU 环境下有着比 Serial 更好的表现;
Parallel Scavenge 收集器 ( 复制算法 ): 新生代并行收集器,追求高吞吐量,高效利用 CPU 。吞
吐量 = 用户线程时间 /( 用户线程时间 +GC 线程时间 ) ,高吞吐量可以高效率的利用 CPU 时间,尽
快完成程序的运算任务,适合后台应用等对交互相应要求不高的场景;
Serial Old 收集器 ( 标记 - 整理算法 ): 老年代单线程收集器, Serial 收集器的老年代版本;
Parallel Old 收集器 ( 标记 - 整理算法 ) : 老年代并行收集器,吞吐量优先, Parallel Scavenge
集器的老年代版本;
CMS(Concurrent Mark Sweep) 收集器(标记 - 清除算法): 老年代并行收集器,以获取最短回
收停顿时间为目标的收集器,具有高并发、低停顿的特点,追求最短 GC 回收停顿时间。
G1(Garbage First) 收集器 ( 标记 - 整理算法 ) Java 堆并行收集器, G1 收集器是 JDK1.7 提供的一
个新收集器, G1 收集器基于 标记 - 整理 算法实现,也就是说不会产生内存碎片。此外, G1
集器不同于之前的收集器的一个重要特点是: G1 回收的范围是整个 Java ( 包括新生代,老年
) ,而前六种收集器回收的范围仅限于新生代或老年代。
ZGC Z Garbage Collector )是一款由 Oracle 公司研发的,以低延迟为首要目标的一款垃圾收
集器。它是基于动态 Region 内存布局,(暂时)不设年龄分代,使用了读屏障、染色指针和内
存多重映射等技术来实现可并发的标记 - 整理算法的收集器。在 JDK 11 新加入,还在实验阶
段,主要特点是:回收 TB 级内存(最大 4T ),停顿时间不超过 10ms 优点 :低停顿,高吞吐
量, ZGC 收集过程中额外耗费的内存小。 缺点 :浮动垃圾
目前使用的非常少,真正普及还是需要写时间的。
新生代收集器 Serial ParNew Parallel Scavenge
老年代收集器 CMS Serial Old Parallel Old
整堆收集器 G1 ZGC ( 因为不涉年代不在图中 )
31 、如何选择垃圾收集器?
1. 如果你的堆大小不是很大(比如 100MB ),选择串行收集器一般是效率最高的。
参数: - XX:+UseSerialGC
2. 如果你的应用运行在单核的机器上,或者你的虚拟机核数只有单核,选择串行收集器依然是合
适的,这时候启用一些并行收集器没有任何收益。
参数: - XX:+UseSerialGC
3. 如果你的应用是 吞吐量 优先的,并且对较长时间的停顿没有什么特别的要求。选择并行收集
器是比较好的。
参数: - XX:+UseParallelGC 仅供阿里
巴巴面试官参考
4. 如果你的应用对响应时间要求较高,想要较少的停顿。甚至 1 秒的停顿都会引起大量的请求失
败,那么选择 G1 ZGC CMS 都是合理的。虽然这些收集器的 GC 停顿通常都比较短,但它
需要一些额外的资源去处理这些工作,通常吞吐量会低一些。
参数:
- XX:+UseConcMarkSweepGC
- XX:+UseG1GC
- XX:+UseZGC 等。
从上面这些出发点来看,我们平常的 Web 服务器,都是对响应性要求非常高的。选择性其实就集
中在 CMS G1 ZGC 上。而对于某些定时任务,使用并行收集器,是一个比较好的选择。

 

你可能感兴趣的:(JVM,小白学java,jvm,学习,java)