JVM笔记


尚硅谷有一套jvm相关的视频,感兴趣的朋友可以看看!这里是根据其中内容做的一些笔记。

一. jvm参数类型

1. 标配参数

  • java -version
  • java -help
  • java -showversion

2. X参数(了解)

  • -Xint 解释执行
  • -Xcomp 第一次使用就编译成本地代码
  • -Xmixed 混合模式(先编译再执行)

3. XX参数

  • boolean 类型

    公式:-XX:+ or - 某个属性

    +:表示开启

    -: 表示关闭

    • 是否打印GC收集细节
      • -XX:+PrintGcDetails
      • -XX:-PrintGcDetails
    • 是否使用串行垃圾回收器
  • KV设置类型

    公式: -XX:属性key=属性值value

    • -XX:MetaspaceSize=128m
    • -XX:MaxTenuringThreshold=15
  • jinfo举例,如何查看当前运行程序的配置(查看某个配置是否被激活)

    公式:jinfo -flag 配置项 进程编号

    jinfo -flags 进程编号

    • jinfo -flag PrintGcDetails 13632(进程号 ps -l获取)
    [asdsw@izuf6ekene8xsqnzg2v3qcz deploy]$ jinfo -flags 8771
    Attaching to process ID 8771, please wait...
    Debugger attached successfully.
    Server compiler detected.
    JVM version is 25.191-b12
    Non-default VM flags: -XX:CICompilerCount=2 -XX:InitialHeapSize=31457280 -XX:MaxHeapSize=482344960 -XX:MaxNewSize=160759808 -XX:MinHeapDeltaBytes=196608 -XX:NewSize=10485760 -XX:OldSize=20971520 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops
    Command line:
  • 题外话

    -Xms1024m (默认1/64 物理内存)

    -Xmx1024m(默认1/4 物理内存)

    • -Xms => -XX:InitialHeapSize=
    • -Xmx => -XX:MaxHeapSize=

二. 盘点家底查看JVM默认值

1. -XX:+PrintFlagsInitial

主要查看初始默认值

java -XX:+PrintFlagsInitial -version

java -XX:+PrintFlagsInitial

2. -XX:+PrintFlagsFinal

主要查看修改更新

java -XX:+PrintFlagsFinal -version

java -XX:+PrintFlagsFinal

注意 = 和 :=区别, := 代表由JVM或者人为改动过

3. PrintFlagsFinal举例,运行java命令的同时打印出参数

java -XX:+PrintFlagsInitial -XX:MetaspaceSize=50m Test(测试程序)

4. -XX:+PrintCommandLineFlags

 ✘ ishiv@shiweideMacBook-Pro  ~  java -XX:+PrintCommandLineFlags -version
-XX:InitialHeapSize=134217728 -XX:MaxHeapSize=2147483648 -XX:+PrintCommandLineFlags -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseParallelGC
java version "1.8.0_181"
Java(TM) SE Runtime Environment (build 1.8.0_181-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.181-b13, mixed mode)

三. 常用参数

1. -Xms

初始化内存大小,默认为物理内存1/64

等价于-XX:InitialHeapSize

2. -Xmx

最大内存分配,默认为物理内存1/4

等价于-XX:MaxHeapSize

3. -Xss

设置单个线程栈的大小,一般默认为512k-1024k,依赖具体平台

等价于-XX:ThreadStackSize

4. -Xmn

设置年轻代大小,新生代默认Heap 1/3

5. -XX:MetaspaceSize

元空间的本质和永久代类似,都是对JVM规范中方法区的实现,不过元空间并不在虚拟机中,而是使用本地内存,因此默认情况下,元空间的大小受本地内存限制。

-Xms10m -Xmx10m -XX:MetaspaceSize=1024m -XX:+PrintFlagsFinal -XX:+PrintGCDetails -XX:+UseSerailGC

6. -XX:PrintGCDetails

GC:

gc-log

FullGC:

fullgc-log

7. -XX:SurvivorRatio

设置新生代中eden和S0/S1空间的比例

默认:

-XX:SurvivorRatio=8, Eden:S0:S1=8:1:1

8. -XX:NewRatio

配置年轻代与老年代在堆结构的占比

默认

-XX:NewRatio=2新生代占1,老年代2,年轻代占整个堆的1/3

9. -XX:MaxTenuringThreshould

该参数主要是控制新生代需要经历多少次GC晋升到老年代中的最大阈值。在JVM中用4个bit存储(放在对象头中),所以其最大值是15。
但并非意味着,对象必须要经历15次YGC才会晋升到老年代中。例如,当survivor区空间不够时,便会提前进入到老年代中,但这个次数一定不大于设置的最大阈值。

Java8 这个值只能在0-15之间

四. 垃圾回收器

 一. 部分参数预先说明:

DefNew: Default New Generation

Tenured: Old

ParNew: Parallel New Generation

PSYongGen: Parallel Scavenge

ParOldGen: ParallelOldGeneration

二. server/client

1.1 32位Windows操作系统,不论硬件如何都默认使用client的JVM模式

1.2 32位其它操作系统,2G内存同时又2个cpu以上用server模式,低于该配置还是Client模式

2.3 64位only server模式

gc_3

gc_4

gc_5jpg

gc_6jpg

1. 串行垃圾回收器(Serial)

它为单线程环境设计且只有一个线程进行垃圾回收,并且会暂停所有的用户线程。所以不合适服务器环境

2. 并行垃圾回收器(Parallel)

多个垃圾收集线程并行工作,此时用户线程是暂停的,适用于科学计算、大数据处理等若交互场景

3. 并行垃圾回收器(CMS)

用户线程和垃圾收集线程同时执行,不需要停顿用户线程(其实有两步也需要,但是停顿时间很短),互联网公司多用它,适应队响应时间有要求的场景。

4. G1垃圾回收器

G1垃圾回收器将堆内存分割成不同的区域然后并发的对其进行垃圾回收

-XX:UseG1GC

1. 之前收集器的特点
  • 年轻代和老年代是各自独立且连续的内存块
  • 年轻代收集使用单eden+s0+s1进行复制算法
  • 老年代收集必须扫描整个老年代区域
  • 都是以尽可能少而快速地执行GC为设计原则
2. G1是什么

Garbage-First收集器,是一款面向服务端应用的收集器,应用在多处理器和大容量的内存环境中,在实现高吞吐量的同时,尽可能的满足垃圾收集暂停时间的要求。

特性:

像CMS收集器一样,能与应用程序并发执行

整理空闲空间更快

需要更多的时间来预测GC停顿时间

不希望牺牲大量的吞吐性能

不需要更大的Java Heap

G1收集器的设计目标是取代CMS,它同CMS相比,在以下方面表现的更为出色:

  • G1是一个有整理内存过程的垃圾收集器,不会产生很多内存碎片
  • G1的Stop The World更可控,G1在停顿时间上添加了预测机制,用户可以指定期望停顿时间

CMS垃圾收集器虽然减少了暂停应用程序的运行时间,但是它还是存在着内存碎片的问题。于是,为了去除内存碎片问题,同时又保留CMS垃圾收集器地暂停时间的优点,JAVA7发布了一个新的垃圾收集器-G1

G1是在2012年在jdk1.7u4中可用。oracle官方计划在jdk9中将G1变成默认的垃圾收集器以替代CMS。它是一款面向服务端应用的收集器,主要应用在多CPU和大内存服务器环境下,极大的减少垃圾收集的停顿时间,全面提升服务器的性能,逐步替换java8以前的CMS收集器。

主要改变是Eden,Survivor和Tenured等内存区域不再是连续的了,而是变成一个个大小一样的region,没人region从1M-32M不等。一个region有可能属于eden,survivor或者Tenured内存区域。

特点:

  • G1能充分利用多CPU,多核环境硬件优势,尽量缩短STW
  • G1整体上采用标记-整理算法,局部是通过复制算法,不回产生内存碎片
  • 宏观上看G1之中不再区分年轻代和老年代。把内存划分成多个独立的子区域(Region),可以近似理解为一个围棋的棋盘。
  • G1收集器里面将整个的内存区都混合在一起了,但其本身依然在小范围内进行年轻代和老年代的区分,保留了新生代和老年代,但是他们不再是物理隔离的,而是一部分region的集合且不需要region是连续的,也就是说依然会采用不同的GC方式来处理不同的区域。
  • G1虽然也是分代收集器,但整个内存分区不存在物理上的年轻代与老年代的区别,也不需要完全独立的survivor(to space)堆做复制准备。G1只有逻辑上的分代概念,或者说每个分区都可能随G1的运行在不同代之间前后切换。
3. 常见参数配置

-XX:+UseG1GC

-XX:G1HeapRegionSize=n: 设置G1区域大小,大小为2的幂,范围是1m-32m.目标是根据最下的java堆大小划分出约2048个区域

-XX:MaxGCPauseMillis=n: 最大GC停顿时间,这是个软目标,JVM将尽可能(但不保证)停顿小于这个时间

-XX:InitiatingHeapOccupancyPercent=n: 堆占用了多少的时候触发GC,默认45

-XX:ConcGCThreads=n: 并发GC使用的线程数

-XX:G1ReservePercent=n: 设置作为空闲的预留内存百分比,以降低目标空间溢出的风险,默认是10%

4. 与CMS对比优势
  • G1不会产生内存碎片
  • 可以精确控制停顿。把整个堆划分成多个固定大小的区域,每次根据允许停顿时间去收集垃圾最多的区域

5. 新生代

1. 串行收集器Serial

最古老,最稳定以及效率最高的收集器,只使用一个线程去回收但其在进行垃圾收集过程中可能会产生较长的停顿。虽然在手机垃圾过程中需要暂停所有其他的工作线程,但是它简单高效,对于限定单个CPU环境来说,没有线程交互的开销可以获得最高的单线程垃圾收集效率,因此Serial垃圾收集器依然是java虚拟机在Client模式下默认的新生代垃圾收集器。

对应的JVM参数: -XX:+UseSerialGC

开启后会使用:Serail(Young区用) + Serial Old(Old区用)的收集器组合

表示: 新生代,老年代都会使用串行回收器,新生代使用复制算反,老年代使用标记-整理算法。

2. ParNew 并行收集器

使用多线程进行垃圾回收,在垃圾收集时,会STW暂停其它所有的工作线程直到它收集结束。

是Serial收集器新生代的并行多线程版本,最常见的场景就是配合老年代的CMS GC工作,其余的行为和Serial收集器完成一样,ParNew垃圾收集器在垃圾收集过程中同样也要暂停其它的工作线程。它是很多java虚拟机在Server模式下新生代的默认垃圾收集器。

对应的JVM参数: -XX+UseParNewGC

启用ParNew只影响新生代的收集,不影响老年代

开启上述参数后,会使用:ParNew(Young区用)+ Serial Old的收集器组合,新生代使用复制算法,老年代采用标记-整理算法。

但是,ParNew + Tenured这样的搭配,java8已结不再被推荐。

3. 并行回收 Parallel Scavenge

Parallel Scavenge收集器类似ParNew,也是一个新生代来及收集器,使用复制算法,也是一个并行的多线程垃圾收集器,俗称吞吐量优先收集器。

它重点关注的是:

可控的吞吐量(thoughput=运行用户代码时间/(运行用户代码时间 + 垃圾收集时间)), 也即比如程序运行100分钟,垃圾收集时间1分钟,吞吐量就是99%。高吞吐量意味着高效利用CPU的时间,它多用于后台运算而不太需要太多交互的任务。

自适应调解策略也是ParallelScavenge收集器与ParNew收集器的一个重要区别。自适应调解策略:虚拟机会根据当前系统的运行情况收集性能监控信息,动态调整这些参数以提供最合适的停顿时间(-XX:MaxGCPauseMillis)或最大的吞吐量。

常用JVM参数:-XX:+UseParallelGC或-XX:+UseParallelOldGC(可互相激活)使用Parallel Scavenge收集器

-XX:ParallelGCThreads=数字N: 表示启动多个GC线程

6. 老年代

1. 串行GC (Serial Old / Serial MSC)

-XX:+UseSerialOldGC

2. 并行GC(Parallel Old / Parallel MSC)

-XX:+UseParallelOldGC

3. 并发标记清除GC(CMS)

CMS(Concurrent Mark Sweep: 并发标记清除),是一种以获取最短回收停顿时间为目标的收集器。适合应用在互联网或者B/S系统的服务器上,这类应用尤其重视服务器的响应速度,希望停顿时间最短。CMS非常适合堆内存大,CPU核数多的服务器端应用,也是G1出险之前大型应用的首选收集器。

开启该收集器的JVM参数:-XX:+UseConcMarkSweepGC,开启该参数后会自动将: -XX:+UseParNewGC打开。

开启该参数后,使用ParNew(Yong区用) + CMS(Old区用) + Serial Old的收集器组合,Serial Old将作为CMS的后备收集器

4步过程:

  • 初始标记(CMS initial mark)
  • 并发标记(CMS concurrent mark) : 和用户线程一起
  • 重新标记(CMS remark)
  • 并发清除(CMS concurrent sweep):和用户线程一起

优缺点:

优: 停顿低

缺: 并发执行,对cpu压力较大;采用标记清除会导致碎片

标记清除算法无法整理空间碎片,老年代空间会随着应用时长被逐步耗尽,最后将不得不通过担保机制对内存进行压缩。CMS也提供了参数-XX:CMSFullGCsBeforeCompaction(默认0,即每次都进行内存整理)来指定多少次CMS收集之后,进行一次压缩的Full GC;


文章作者: shiv
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 shiv !
评论
  目录