JVM命令

282 阅读4分钟

大纲:

命令简介 --> 命令与生产实践间的关联

1. 命令简介:

jps:当前所有java进程pid,


jstat:用于查询JVM内存使用情况和GC次数及耗时;


参数列表含义

  • S0C:年轻代中第一个survivor(幸存区)的容量 (字节)
  • S1C:年轻代中第二个survivor(幸存区)的容量 (字节)
  • S0U :年轻代中第一个survivor(幸存区)目前已使用空间 (字节)
  • S1U :年轻代中第二个survivor(幸存区)目前已使用空间 (字节)
  • EC :年轻代中Eden(伊甸园)的容量 (字节)
  • EU :年轻代中Eden(伊甸园)目前已使用空间 (字节)
  • OC :Old代的容量 (字节)
  • OU :Old代目前已使用空间 (字节)
  • MC:metaspace(元空间)的容量 (字节)
  • MU:metaspace(元空间)目前已使用空间 (字节)
  • YGC :从应用程序启动到采样时年轻代中gc次数
  • YGCT :从应用程序启动到采样时年轻代中gc所用时间(s)
  • FGC :从应用程序启动到采样时old代(全gc)gc次数
  • FGCT :从应用程序启动到采样时old代(全gc)gc所用时间(s)
  • GCT:从应用程序启动到采样时gc用的总时间(s)
常用jstat命令
  • jstat -gc pid :打印pid的java进程的gc详情
  • jstat -gc pid 1000 10 :每隔1秒打印一次gc详情,打印10次

jmap:它可以生成 java 程序的 dump 文件, 也可以查看堆内对象示例的统计信息、查看 ClassLoader 的信息以及 finalizer 队列

我常用其打印dumo文件,用作MAT分析

jmap -dump:format=b,file=heapdump.phrof pid

jstack:查询线程情况

2. 命令与生产实践间的关联

如何感知内存增长速率,及常见的fullGC及内存分配问题

首先根据前面总结的知识点,我们可以通过jstat -gc pid,来了解到以下信息:

  1. 了解GC内存分配情况,分配的是否合理有一个最初的感知;
  2. 通过GC时长和GC的次数,计算出每次GC的耗时,这样我们就知道了FullGC的触发时间频率,及GC的平均时长;
jstat -gc pid 1000 10
  1. 通过观察最近一段时间的gc情况,可以看到内存数据的增长情况,对数据的增加速率有一定的了解;
  2. 通过每次GC之后,数据是迁移到survivor区还是迁移到老年代有一个清晰认知;
  3. 每次gc之后,对存活对象的大小有感知,方便合理的设置内存
通过上面这些信息,我们就可以很方便的定位到常见的fullGC触发的原因,并且合理的优化内存大小。


由大对象引发的问题

首先先说一下大对象引入的几种场景:

  1. 由于sql不合理,导致将全表数据都查询出来;
  2. 由于要将大量数据加载到内存中,进行计算;


由于 重试机制 或 超时时间 引发的问题

假如对方系统出现问题,由于超时时间过长,或 重试机制设置不合理,会导致我们的系统大量的请求积压进来,长时间不能释放对象,从而导致频繁的gc,这就需要我们通过jmap dump文件,来查看大量存活的对象是哪些?查看其堆栈信息,定位到代码位置,对代码进行分析测试定位。


由于反射或-XX:SoftRefLRUPolicyMSPerMB参数设置不合理引发的问题

首先,这个问题不常见,也不建议设置此参数,关于这块的内存,详见此篇文章

blog.csdn.net/qiang_zi_/a…


System.gc()引发的问题

因为System.gc()会触发fullGC,所以建议系统内不要写System.gc()


CPU负载过高常见的场景

  1. 系统创建了大量的线程,并行运行,而且工作负载都很重。
  2. FullGC是非常耗费cpu资源的,如果频繁触发fullGC,会导致cpu负载过高

频繁fullGC的场景

  1. 内存分配不合理,导致对象频繁进入老年代;
  2. 存在内存泄漏等问题,导致大量对象塞满了老年代;
  3. 永久代里的类太多,触发了fullGC


NIO DirectByteBuffer导致的堆外内存溢出

由于大量DirectByteBuffer对象因某种原因,进入了老年代,DirectByteBuffer对象长时间没有被回收,导致堆外内存也无法被回收,最终导致内存溢出