JVM 监控以及内存分析

62 篇文章 3 订阅
33 篇文章 1 订阅

Java 语言,开发者不能直接控制程序运行内存,对象的创建都是由类加载器一步步解析,执行与生成与内存区域中的;并且 jvm 有自己的垃圾回收器对内存区域管理、回收;但是我们已经可以通过一些工具来在程序运行时查看对应的 jvm 内存使用情况,帮助更好的分析与优化我们的代码。

查看系统里 java 进程信息

// 查看当前机器上所有运行的java进程名称与pid(进程编号)
jps -l
// 显示指定的jvm进程所有的属性设置和配置参数
jinfo pid

jmap -histo

查看类的内存占用

$ pid=\`jps | awk '{if ($2 == "Bootstrap") print $1}'`
$ jmap -histo $pid >>1.jmap

 num     #instances         #bytes  class name
----------------------------------------------
   1:         16226      862336904  [Ljava.util.HashMap$Node;
   2:        230727       14940520  [B
   3:          5105       14082960  [I
   4:        205826       12756064  [C
   5:        150472        4815104  java.util.HashMap$Node
   6:        186884        4485216  java.lang.String
   7:        277734        4443744  java.lang.Integer
   8:        108699        4347960  com.jiemo.school.model.impl.SchoolModel
   9:        128405        4108960  java.util.concurrent.ConcurrentHashMap$Node
  10:           114        1512448  [Ljava.util.concurrent.ConcurrentHashMap$Node;
  11:         34496        1511024  [Ljava.lang.Object;
  12:         25702        1233696  java.nio.HeapByteBuffer
  13:         34277        1096864  java.util.concurrent.locks.AbstractQueuedSynchronizer$Node
  14:          7665         856392  java.lang.Class
  15:         18725         749000  java.util.HashMap$KeyIterator
  16:         14489         695472  java.nio.HeapCharBuffer
  17:         28122         674928  java.util.ArrayList
  18:         25272         642776  [Ljava.lang.String;
  19:         15380         615200  java.net.DatagramPacket

class name 解读
B 代表 byte
C 代表 char
D 代表 double
F 代表 float
I 代表 int
J 代表 long
Z 代表 boolean
前边有 [代表数组,[I 就相当于 int[]
对象用 [L + 类名表示

如果某个类的个数特别多, 就得检查是否内存溢出了。

jmap -heap

$ jmap -heap 22792
Attaching to process ID 19395, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.45-b02

using thread-local object allocation.
Parallel GC with 8 thread(s)

Heap Configuration:
   MinHeapFreeRatio         = 0                            # 对应jvm启动参数 -XX:MinHeapFreeRatio 设置JVM堆最小空闲比率 (默认40)
   MaxHeapFreeRatio         = 100                          # 对应jvm启动参数 -XX:MaxHeapFreeRatio 设置JVM堆最大空闲比率 (默认70)
   MaxHeapSize              = 8388608000 (8000.0MB)        # 对应jvm启动参数 -XX:MaxHeapSize 设置JVM堆的最大大小
   NewSize                  = 44564480 (42.5MB)            # 对应jvm启动参数 -XX:NewSize 设置JVM堆的年轻代的默认大小
   MaxNewSize               = 2796027904 (2666.5MB)        # 对应jvm启动参数 -XX:MaxNewSize 设置JVM堆的年轻带的最大大小
   OldSize                  = 89653248 (85.5MB)            # 对应jvm启动参数 -XX:OldSize 设置JVM堆的老年代的大小
   NewRatio                 = 2                            # 对应jvm启动参数 -XX:NewRatio 老年代与年轻代的大小比率
   SurvivorRatio            = 8                            # 对应jvm启动参数 -XX:SurvivorRatio 设置年轻代中Eden区与Survivor区的大小比值
   MetaspaceSize            = 21807104 (20.796875MB)       # -XX:MetaspaceSize
   CompressedClassSpaceSize = 1073741824 (1024.0MB)        # -XX:CompressedClassSpaceSize, 只有当-XX:+UseCompressedClassPointers开启了才有效
   MaxMetaspaceSize         = 536870912 (512.0MB)          # -XX:MaxMetaspaceSize
   G1HeapRegionSize         = 0 (0.0MB)

Heap Usage:
PS Young Generation
Eden Space:                                         # Eden区内存分布 总量 已使用 空闲 使用比率
   capacity = 404750336 (386.0MB)
   used     = 376643272 (359.1950149536133MB)
   free     = 28107064 (26.80498504638672MB)
   93.05570335585837% used
From Space:                                         # 其中一个Survivor区内存分布 总量 已使用 空闲 使用比率
   capacity = 458227712 (437.0MB)
   used     = 383131152 (365.38233947753906MB)
   free     = 75096560 (71.61766052246094MB)
   83.61151933124464% used
To Space:                                           # 另一个Survivor区内存分布 总量 已使用 空闲 使用比率
   capacity = 492830720 (470.0MB)
   used     = 0 (0.0MB)
   free     = 492830720 (470.0MB)
   0.0% used
PS Old Generation                                   # 当前老年代内存分布 总量 已使用 空闲 使用比率
   capacity = 918552576 (876.0MB)
   used     = 463923192 (442.43163299560547MB)
   free     = 454629384 (433.56836700439453MB)
   50.50589417758053% used


16117 interned Strings occupying 1692808 bytes.

MaxHeapFreeRatio: GC 后如果发现空闲堆内存占到整个预估堆内存的 N%(百分比),则收缩堆内存的预估最大值, 预估堆内存是堆大小动态调控的重要选项之一. 堆内存预估最大值一定小于或等于固定最大值 (-Xmx 指定的数值). 前者会根据使用情况动态调大或缩小, 以提高 GC 回收的效率
MinHeapFreeRatio: GC 后如果发现空闲堆内存占到整个预估堆内存的 N%(百分比), 则放大堆内存的预估最大值

MaxHeapSize: 即 - Xmx, 堆内存大小的上限
InitialHeapSize: 即 - Xms, 堆内存大小的初始值

NewSize: 新生代预估堆内存占用的默认值
MaxNewSize: 新生代占整个堆内存的最大值

OldSize: 老年代的默认大小, default size of the tenured generation
NewRatio: 老年代对比新生代的空间大小, 比如 2 代表老年代空间是新生代的两倍大小. The ratio of old generation to young generation.

SurvivorRatio: Eden/Survivor 的值. 这个值的说明, 很多网上转载的都是错的. 8 表示 Survivor:Eden=1:8, 因为 survivor 区有 2 个, 所以 Eden 的占比为 8/10. Ratio of eden/survivor space size. -XX:SurvivorRatio=6 sets the ratio between each survivor space and eden to be 1:6, each survivor space will be one eighth of the young generation.

MetaspaceSize: 分配给类元数据空间的初始大小 (Oracle 逻辑存储上的初始高水位,the initial high-water-mark). 此值为估计值. MetaspaceSize 设置得过大会延长垃圾回收时间. 垃圾回收过后, 引起下一次垃圾回收的类元数据空间的大小可能会变大
MaxMetaspaceSize: 是分配给类元数据空间的最大值, 超过此值就会触发 Full GC. 此值仅受限于系统内存的大小, JVM 会动态地改变此值

CompressedClassSpaceSize: 类指针压缩空间大小, 默认为 1G

G1HeapRegionSize: G1 区块的大小, 取值为 1M 至 32M. 其取值是要根据最小 Heap 大小划分出 2048 个区块. With G1 the Java heap is subdivided into uniformly sized regions. This sets the size of the individual sub-divisions. The default value of this parameter is determined ergonomically based upon heap size. The minimum value is 1Mb and the maximum value is 32Mb. Sets the size of a G1 region. The value will be a power of two and can range from 1MB to 32MB. The goal is to have around 2048 regions based on the minimum Java heap size.

指针压缩

  1. 64 位平台上默认打开
    1) 使用 - XX:+UseCompressedOops 压缩对象指针
    “oops” 指的是普通对象指针 (“ordinary” object pointers)。
    Java 堆中对象指针会被压缩成 32 位。
    使用堆基地址(如果堆在低 26G 内存中的话,基地址为 0)
    2) 使用 - XX:+UseCompressedClassPointers 选项来压缩类指针
    对象中指向类元数据的指针会被压缩成 32 位
    类指针压缩空间会有一个基地址
  2. 元空间和类指针压缩空间的区别
    1) 类指针压缩空间只包含类的元数据,比如 InstanceKlass, ArrayKlass
    仅当打开了 UseCompressedClassPointers 选项才生效
    为了提高性能,Java 中的虚方法表也存放到这里
    这里到底存放哪些元数据的类型,目前仍在减少
    2) 元空间包含类的其它比较大的元数据,比如方法,字节码,常量池等。

jstat -gcutil [pid] [internal]

 S0     S1     E      O      M     CCS     YGC     YGCT     FGC    FGCT     GCT
83.61   0.00  93.25  50.51  97.92  93.98   32     45.703    10    16.852   62.555

S0: Survivor 0 区的空间使用率 Survivor space 0 utilization as a percentage of the space’s current capacity.
S1: Survivor 1 区的空间使用率 Survivor space 1 utilization as a percentage of the space’s current capacity.
E: Eden 区的空间使用率 Eden space utilization as a percentage of the space’s current capacity.
O: 老年代的空间使用率 Old space utilization as a percentage of the space’s current capacity.
M: 元数据的空间使用率 Metaspace utilization as a percentage of the space’s current capacity.
CCS: 类指针压缩空间使用率 Compressed class space utilization as a percentage.
YGC: 新生代 GC 次数 Number of young generation GC events.
YGCT: 新生代 GC 总时长 单位秒 Young generation garbage collection time.
FGC: Full GC 次数 Number of full GC events.
FGCT: Full GC 总时长 单位秒 Full garbage collection time.
GCT: 总共的 GC 时长 单位秒 Total garbage collection time.

查看 JVM 参数及值的命令行工具

  1. -XX:+PrintFlagsInitial 参数
    显示所有可设置参数及默认值,可结合 - XX:+PrintFlagsInitial 与 - XX:+PrintFlagsFinal 对比设置前、设置后的差异,方便知道对那些参数做了调整。

    $ java -XX:+PrintFlagsInitial
    [Global flags]
        uintx AdaptiveSizeDecrementScaleFactor          = 4                                   {product}
        uintx AdaptiveSizeMajorGCDecayTimeScale         = 10                                  {product}
        uintx AdaptiveSizePausePolicy                   = 0                                   {product}
        uintx AdaptiveSizePolicyCollectionCostMargin    = 50                                  {product}
        uintx AdaptiveSizePolicyInitializingSteps       = 20                                  {product}
        uintx AdaptiveSizePolicyOutputInterval          = 0                                   {product}
        uintx AdaptiveSizePolicyWeight                  = 10                                  {product}
        uintx AdaptiveSizeThroughPutPolicy              = 0                                   {product}
        uintx AdaptiveTimeWeight                        = 25                                  {product}
         bool AdjustConcurrency                         = false                               {product}
         bool AggressiveOpts                            = false                               {product}
         intx AliasLevel                                = 3                                   {C2 product}
         bool AlignVector                               = true                                {C2 product}
         intx AllocateInstancePrefetchLines             = 1                                   {product}
         intx AllocatePrefetchDistance                  = -1                                  {product}
         intx AllocatePrefetchInstr                     = 0                                   {product}
         intx AllocatePrefetchLines                     = 3                                   {product}
         intx AllocatePrefetchStepSize                  = 16                                  {product}

     

  2. -XX:+PrintFlagsFinal 参数
    可以获取到所有可设置参数及值 (手动设置之后的值),这个参数只能使用在 Jdk6 update 21 以上版本 (包括该版本)。-XX:+PrintFlagsFinal 参数的使用 与上面 - XX:+PrintFlagsInitial 参数使用相同

    Java -XX:+PrintFlagsFinal

    使用 jinfo 命令 查看或设置某个参数的值,jinfo 命令格式:

  3. jinfo [option] <pid>

     

jcmd

在 JDK 1.7 之后,新增了一个命令行工具 jcmd。它是一个多功能工具,可以用来导出堆,查看 Java 进程,导出线程信息,执行 GC 等。

  • 列出当前运行的所有虚拟机

    [root@apple ~]# jcmd -l
    30356 com.aliyun.tianji.cloudmonitor.Application
    8757 org.jruby.Main /opt/logstash/lib/bootstrap/environment.rb logstash/runner.rb -f /etc/logstash/conf.d/event-operate-post-shipper.yaml
    8713 org.jruby.Main /opt/logstash/lib/bootstrap/environment.rb logstash/runner.rb -f /etc/logstash/conf.d/statistics-shipper.yaml
    11615 sun.tools.jcmd.JCmd -l
    21167 org.apache.catalina.startup.Bootstrap start
    [root@apple ~]#
     

    参数-l表示列出所有 java 虚拟机,针对每一个虚拟机,可以使用 help 命令列出该虚拟机支持的所有命令,如下图所示,以 21167 这个进程为例:

    [root@apple ~]# jcmd 21167 help
    21167:
    The following commands are available:
    JFR.stop
    JFR.start
    JFR.dump
    JFR.check
    VM.native_memory
    VM.check_commercial_features
    VM.unlock_commercial_features
    ManagementAgent.stop
    ManagementAgent.start_local
    ManagementAgent.start
    GC.rotate_log
    Thread.print
    GC.class_stats
    GC.class_histogram
    GC.heap_dump
    GC.run_finalization
    GC.run
    VM.uptime
    VM.flags
    VM.system_properties
    VM.command_line
    VM.version
    help
    
    For more information about a specific command use 'help <command>'.

    查看虚拟机启动时间 VM.uptime

  • [root@apple ~]# jcmd 21167 VM.uptime
    21167:
    527760.414 s

     

  • 打印线程栈信息 Thread.print

  • 查看系统中类统计信息 GC.class_histogram
  • 导出堆信息 GC.heap_dump(这个命令可以导出当前堆栈信息,功能和jmap -dump功能一样)
  • 获取系统 Properties 内容 VM.system_properties
  • 获取启动参数 VM.flags
  • 获取所有性能相关数据 PerfCounter.print

总结:jcmd 拥有 jmap 的大部分功能,并且 Oracle 官方也建议使用 jcmd 代替 jmap。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值