JVM知识点以及常用参数及工具

目录

 

基础知识

JVM运行时内存消耗是指哪些方面

分代内存管理

Stop the World(STW)

Concurrent 和 STW 的GC对比

Young GC(Minor GC)

Full GC(Major GC)

常用GC

并行收集器

Concurrent Mark-Sweep(CMS) 收集器

G1收集器

常用JVM参数

常用JVM工具

jps

jstat

jmap

jstack

MAT(Memory Analyzer (MAT) )

Flight Recorder


基础知识

JVM运行时内存消耗是指哪些方面

JVM运行时内存消耗通常包含以下几个部分:

  1. Heap:我们常说的JVM运行时堆内存(通过-Xmx, -Xms参数控制)
  2. 所有线程占用的Thread Stack:Java的每一个线程最多会占用一个Thread Stack大小的内存(通过-Xss参数控制)
  3. Direct Memory:一些网络编程框架常会使用,如,Netty(通过-XX:MaxDirectMemorySize参数控制)
  4. JNI Native Memory:一些通过JNI实现的库会使用,如,压缩用到的Deflater
  5. Meta Space(JDK8)/ Perm Gen(JDK7)(通过-XX:MaxPermSize、-XX:MaxMetaspaceSize参数控制)
  6. Code Cache:用于编译和保存本地代码(native code)的内存(通过-XX:ReservedCodeCacheSize参数控制)
  7. JVM自身使用的内存:存储一些JVM内部的数据结构(如,GC用到的数据结构)

内存布局如下图:

分代内存管理

Hotspot虚拟机的heap内存被划分成Young区和Old区。

  • Young区:包含一个Eden区和两个Survivor区,当此区域用完时会发生Young GC(或者叫做Minor GC)。绝大部分对象都在Eden区分配,至少经过一次Young区垃圾回收后依然存活的对象会被移到Survivor区。两个Survivor区同一时间只有一个包含了对象(叫做From区),另外一个为空(叫做To区)。每一次Young GC会把Eden区以及From区存活的对象Copy到To区,GC结束后From区和To区交换,原来的From区变成To区(此时为空),原来的To区叫做From区(此时包含了GC后Eden区及原From区依然存活的对象)。如下图

  • Old区:在Survivor区存活超过一定次数的对象会被移到Old区,也有一部分大对象直接在Old区进行分配。当此区域用完时会发生Full GC(或者叫做Major GC),Full GC发生时会对Young区和Old区都进行垃圾回收

 

Stop the World(STW)

      进程内的所有应用线程停止运行,如果发生STW的时候一个线程正在处理请求(如,一个远程调用请求),则此请求只有STW结束后才会继续执行,所以此请求的处理时间一定大于STW的时间。

 

Concurrent 和 STW 的GC对比

  • Concurrent GC在某些GC阶段还是需要STW的,详见下面CMS的介绍
  • 由于Concurrent GC执行时,GC线程和应用线程同时运行,所以需要关注两个问题:1. CPU使用,GC线程会消耗CPU导致系统CPU变高,当系统CPU不足时可能会导致应用线程的CPU时间片被GC线程抢占而导致处理变慢;2. 因为GC发生时应用线程仍在运行,同时也会产生内存分配,所以需要提前进行Concurrent GC,保证heap内可用内存足以支撑正在同时运行的应用线程对内存分配的需求。否则,Concurrent GC会失败,然后重新进入STW的GC

 

Young GC(Minor GC)

  • 不管哪种GC算法,Young GC都会STW
  • 存活对象会被Copy到Survivor区,GC后的Eden区和另外一个Survivor区只包含不再被引用的对象,这两块区域可以被完全重新使用而不需要进行内存碎片整理。所以Young GC的耗时只和Young区存活的对象数量和引用关系复杂度有关,和Young区大小无关
  • 在Survivor区存活时间超过一定次数(-XX:MaxTenuredThreshold)的对象将会移动到Old区
  • 如果存活对象大于一个Survivor区,则全部移动到Old区

 

Full GC(Major GC)

  • 对整个Heap进行回收,不仅限于Old区
  • 耗时和整个Heap大小、存活对象数量,对象之间引用关系有关

 

常用GC

  • Young区
    • 串行Copy收集器(-XX:+UseSerialGC):单线程,STW,Old区可以使用串行收集器或者CMS收集器
    • PS Scavenge收集器(-XX:+UseParallelGC):并行,STW,Old区可以使用串行收集器或者PS MarkSweep收集器
    • ParNew收集器(-XX:+UseParNewGC):并行,STW,Old区可以使用串行收集器或者CMS收集器
    • G1收集器(-XX:+UseG1GC):并行,STW,Old区也使用G1
  • Old区
    • 串行MarkSweepCompact收集器(-XX:+UseSerialGC):单线程,STW
    • PS MarkSweep收集器(-XX:+UseParallelOldGC,设置了这个后自动会设置-XX:+UseParallelGC):并行,STW
    • Concurrent Mark-Sweep收集器(CMS, -XX:+UseConcMarkSweepGC):部分阶段并行(STW),部分阶段并发
    • G1(-XX:+UseG1GC)收集器:部分阶段并行(STW),部分阶段并发

 

并行收集器

  • 整个回收过程STW
  • 由于整个过程STW,不需要担心回收过程中产生新的对象,且CPU资源可以被GC线程充分利用,所以回收的效率和吞吐都比较高,适合于后台运算而不需要太多交互(对响应时间要求不高)的应用(如后台批处理任务,异步消息消费者等)

 

Concurrent Mark-Sweep(CMS) 收集器

  • 由于是Concurrent的,所以适合对响应时间要求高,且CPU资源比较充裕的应用

  • 需要考虑的点请参看上面关于“Concurrent和STW的GC对比”

  • 当剩余内存不足以完成Concurrent回收时,退化成单线程的Full GC
  • 不一定会进行内存整理,所以需要考虑内存碎片问题
  • 整个过程中依然存在STW阶段,Remark阶段STW且多线程并行,见下图

 

G1收集器

  • 设计初衷用于替换CMS收集器,适合大堆(>=6G)
  • 和CMS收集器类似,可以并发执行,但是G1会进行内存整理
  • STW时间可控
  • 当发生Full GC时单线程执行

 

常用JVM参数

参数

描述

-Xms

初始堆大小
-Xmx最大堆大小
-XmnYoung区大小(初始和最大值均为此值)
-Xss每个线程的Stack大小
-XX:PermSize=size初始Perm Gen大小
-XX:MaxPermSize=size最大Perm Gen大小
-XX:NewSize=size初始Young区大小
-XX:MaxNewSize=size最大Young区大小
-XX:MetaspaceSize=size当meta space大小超过此值时,会触发一次GC
-XX:MaxMetaspaceSize=size最大meta space大小

-XX:ReservedCodeCacheSize=size

最大Code Cache大小

-XX:+HeapDumpOnOutOfMemoryError

当发生OOM时,产生heap dump

-XX:HeapDumpPath=path

设置当参数-XX:+HeapDumpOnOutOfMemoryError打开时heap dump文件存放的路径和文件名
-XX:NewRatio=ratio设置young区和old区的比例
-XX:+PrintGC每次GC发生时打印GC信息
-XX:+PrintGCTimeStamps每次GC发生时打印时间戳
-XX:+PrintGCDetails每次GC发生时打印GC详细信息
-XX:SurvivorRatio=ratio设置eden区和survivor区的比例

 

常用JVM工具

 

jps

      用来查看基于HotSpot的JVM里面中,所有具有访问权限的Java进程的具体状态, 包括进程ID,进程启动的路径及启动参数等等,与unix上的ps类似,但是jps仅显示Java进程。

 

jstat

      用于监控基于HotSpot的JVM,对其堆的使用情况进行实时的命令行的统计。

      常用模式

      • jstat -gc {进程号}:垃圾回收的行为统计
      • jstat -gccapacity {进程号}:同-gc,还会输出Java堆各区域使用到的最大、最小空间
      • jstat -gcutil {进程号}:同-gc,输出的是已使用空间占总空间的百分比
      • jstat -gccause {进程号}:垃圾收集统计概述(同-gcutil),附加最近两次垃圾回收事件的原因
      • jstat -gcnew {进程号}:统计新生代行为
      • jstat -gcold {进程号}:统计老年代行为

 

jmap

     打印出某个java进程(使用pid)内存中所有对象的情况(如:产生那些对象,及其数量)。

     可以用于产生heap dump

    常用模式

      • jmap -dump:live,format=b,file={文件路径和文件名} {进程号}:dump heap到文件,format指定输出格式,live指明是仅包含存活的对象(注意:加上此参数会触发一次Full GC)
      • jmap -heap {进程号}:打印heap的概要信息,GC使用的算法,heap的配置及使用情况,可以用此来判断内存目前的使用情况以及垃圾回收情况
      • jmap -histo {进程号}:打印堆的对象统计,包括对象数、内存大小等等。jmap -histo:live 这个命令执行,JVM会先触发gc,然后再统计信息
      • jmap -permstat {进程号}:打印Java堆内存的永久区的类加载器的智能统计信息。对于每个类加载器而言,它的名称、活跃度、地址、父类加载器、它所加载的类的数量和大小都会被打印。此外,包含的字符串数量和大小也会被打印。

 

jstack

     jstack用于打印出给定的java进程ID的Java堆栈信息

    常用模式

    • jstack {进程号}:打印此Java进程此时的所有运行时线程的堆栈信息

 

MAT(Memory Analyzer (MAT) 

    用于分析heap dump文件,可以用来排查内存泄漏问题、也可以用来对java进程的内存使用情况进行分析

 

Flight Recorder

 用于收集Java进程运行时的诊断信息,内存、cpu使用情况以及各种JVM内部和系统级别的事件,以便对此Java进程进行   Profiling。场景举例如下:

    1. 查看运行时哪些类分配内存最多,方便进行内存使用调优
    2. 查看运行时哪些执行路径占用最多CPU,方便进行CPU调优
    3. 查看上下文切换情况
    4. 查看IO情况
    5. ...

 

以上文章转载自JVM内功心法,供大家参考学习哈!

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值