【JVM】Java命令


一:Java命令

作为一个合格的开发人员,不仅要能写好代码,还有一项很重要的技能就是排查问题。这里提到的排查问题不仅仅是在coding的过程中debug等,还包括的就是线上问题的排查。由于在生产环境中,一般没办法debug,所以我们需要借助一些常用命令来查看运行时的具体情况,这些运行时信息包括但不限于运行日志、异常堆栈、堆使用情况、GC情况、JVM参数情况、线程情况等。

那么我们来介绍常用的Java命令,这些命令都是被存放在JDK安装目录的bin目录中,下面来介绍一下相关命令以及具体使用方式

1、jps:显示所有java进程pid

jps(Java Virtual Machine Process Status Tool)是JDK 1.5提供的一个显示当前所有java进程pid的命令,简单实用,常适合在linux/unix平台上简单察看当前java进程的一些简单情况。

jps类似linux/unix平台上上的ps命令,但是jps只查找查找所有的Java应用程序,包括即使没有使用java执行体的那种(例如,定制的启动器)。另外,jps仅查找当前用户的Java进程,而不是当前系统中的所有进程。

  • 学习一个命令,先来看看帮助,使用jps -help查看帮助:
    在这里插入图片描述

参数介绍:

  • -q:只显示pid,不显示class名称,jar文件名和传递给main()方法的参数。
  • -m:输出传递给main()方法的参数,在嵌入式jvm上可能是null。
  • -l:输出应用程序main class的完整package名 或者 应用程序的jar文件完整路径名。
  • -v:输出传递给JVM的参数。

常用指令:

  • jps:显示当前用户的所有java进程的pid。
  • jps -v 3331:显示虚拟机参数。
  • jps -m 3331:显示传递给main()函数的参数。
  • jps -l 3331:显示主类的全路径。

2、jinfo:实时查看和调整虚拟机参数

主要作用是实时查看和调整虚拟机参数。配置信息包括JAVA系统参数和命令行参数,如果运行在64位虚拟机上运行,需要指定-J-d64参数,如:jinfo -J-d64 -sysprops pid。

由于打印jvm常用信息可以使用Jps命令,并且在后续的java版本中可能不再支持(注:jdk8中已经不支持该命令)。

  • 使用jinfo -help查看帮助:
    在这里插入图片描述
    常用指令:

  • jinfo -flag CMSIniniatingOccupancyFration 1444:查询CMSIniniatingOccupancyFration参数值。


3、jstat:监控虚拟机各种运行状态信息

jstat(JVM Statistics Monitoring Tool)是用于监控虚拟机各种运行状态信息的命令行工具。他可以显示本地或远程虚拟机进程中的类装载、内存、垃圾收集、JIT编译等运行数据,在没有GUI图形的服务器上,它是运行期定位虚拟机性能问题的首选工具。

  • 查看帮助: jstat -help
    在这里插入图片描述
    利用JVM内建的指令对Java应用程序的资源和性能进行实时的命令行的监控,包括了对Heap size和垃圾回收状况的监控。可见,Jstat是轻量级的、专门针对JVM的工具,非常适用。
jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]
  • 参数解释
    Option :选项,我们一般使用 -gcutil 查看gc情况
    vmid : VM的进程号,即当前运行的java进程号
    interval:间隔时间,单位为秒或者毫秒
    count :打印次数,如果缺省则打印无数次
     
    参数intervalcount代表查询间隔和次数,如果省略这两个参数,说明只查询一次

假设需要每250毫秒查询一次进程5828垃圾收集状况,一共查询5次,那命令行如下

jstat -gc 5828 250 5

option:

选项option代表这用户希望查询的虚拟机信息,主要分为3类:类装载、垃圾收集和运行期编译状况,具体选项及作用如下:

  • –class 监视类装载、卸载数量、总空间及类装载所耗费的时间
  • –gc 监视Java堆状况,包括Eden区、2个Survivor区、老年代、永久代等的容量
  • –gccapacity 监视内容与-gc基本相同,但输出主要关注Java堆各个区域使用到* 的最大和最小空间
  • –gcutil 监视内容与-gc基本相同,但输出主要关注已使用空间占总空间的百分比
  • –gccause-gcutil功能一样,但是会额外输出导致上一次GC产生的原因
  • –gcnew 监视新生代GC的状况
  • –gcnewcapacity 监视内容与-gcnew基本相同,输出主要关注使用到的最大和最小空间
  • –gcold 监视老年代GC的状况
  • –gcoldcapacity 监视内容与——gcold基本相同,输出主要关注使用到的最大和最小空间
  • –gcpermcapacity 输出永久代使用到的最大和最小空间
  • –compiler 输出JIT编译器编译过的方法、耗时等信息
  • –printcompilation 输出已经被JIT编译的方法

常用指令:

jstat –class <pid> : 显示加载class的数量,及所占空间等信息
  • Loaded 装载的类的数量
  • Bytes 装载类所占用的字节数
  • Unloaded 卸载类的数量
  • Bytes 卸载类的字节数
  • Time 装载和卸载类所花费的时间
jstat -compiler <pid>:显示VM实时编译的数量等信息
  • Compiled 编译任务执行数量
  • Failed 编译任务执行失败数量
  • Invalid 编译任务执行失效数量
  • Time 编译任务消耗时间
  • FailedType 最后一个编译失败任务的类型
  • FailedMethod 最后一个编译失败任务所在的类及方法
jstat -gc <pid>:可以显示gc的信息,查看gc的次数,及时间
  • S0C 年轻代中第一个survivor(幸存区)的容量 (字节)
  • S1C 年轻代中第二个survivor(幸存区)的容量 (字节)
  • S0U 年轻代中第一个survivor(幸存区)目前已使用空间 (字节)
  • S1U 年轻代中第二个survivor(幸存区)目前已使用空间 (字节)
  • EC 年轻代中Eden(伊甸园)的容量 (字节)
  • EU 年轻代中Eden(伊甸园)目前已使用空间 (字节)
  • OC Old代的容量 (字节)
  • OU Old代目前已使用空间 (字节)
  • PC Perm(持久代)的容量 (字节)
  • PU Perm(持久代)目前已使用空间 (字节)
  • YGC 从应用程序启动到采样时年轻代中gc次数
  • YGCT 从应用程序启动到采样时年轻代中gc所用时间(s)
  • FGC 从应用程序启动到采样时old代(全gc)gc次数
  • FGCT 从应用程序启动到采样时old代(全gc)gc所用时间(s)
  • GCT 从应用程序启动到采样时gc用的总时间(s)
jstat -gccapacity <pid>:可以显示VM内存中三代(young,old,perm)对象的使用和占用大小
  • NGCMN 年轻代(young)中初始化(最小)的大小(字节)
  • NGCMX 年轻代(young)的最大容量 (字节)
  • NGC 年轻代(young)中当前的容量 (字节)
  • S0C 年轻代中第一个survivor(幸存区)的容量 (字节)
  • S1C 年轻代中第二个survivor(幸存区)的容量 (字节)
  • EC 年轻代中Eden(伊甸园)的容量 (字节)
  • OGCMN old代中初始化(最小)的大小 (字节)
  • OGCMX old代的最大容量(字节)
  • OGC old代当前新生成的容量 (字节)
  • OC Old代的容量 (字节)
  • PGCMN perm代中初始化(最小)的大小 (字节)
  • PGCMX perm代的最大容量 (字节)
  • PGC perm代当前新生成的容量 (字节)
  • PC Perm(持久代)的容量 (字节)
  • YGC 从应用程序启动到采样时年轻代中gc次数
  • FGC 从应用程序启动到采样时old代(全gc)gc次数
jstat -gcutil <pid>:统计gc信息
  • S0 年轻代中第一个survivor(幸存区)已使用的占当前容量百分比
  • S1 年轻代中第二个survivor(幸存区)已使用的占当前容量百分比
  • E 年轻代中Eden(伊甸园)已使用的占当前容量百分比
  • O old代已使用的占当前容量百分比
  • P perm代已使用的占当前容量百分比
  • YGC 从应用程序启动到采样时年轻代中gc次数
  • YGCT 从应用程序启动到采样时年轻代中gc所用时间(s)
  • FGC 从应用程序启动到采样时old代(全gc)gc次数
  • FGCT 从应用程序启动到采样时old代(全gc)gc所用时间(s)
  • GCT 从应用程序启动到采样时gc用的总时间(s)
jstat -gcnew <pid>:年轻代对象的信息
  • S0C 年轻代中第一个survivor(幸存区)的容量 (字节)
  • S1C 年轻代中第二个survivor(幸存区)的容量 (字节)
  • S0U 年轻代中第一个survivor(幸存区)目前已使用空间 (字节)
  • S1U 年轻代中第二个survivor(幸存区)目前已使用空间 (字节)
  • TT 持有次数限制
  • MTT 最大持有次数限制
  • EC 年轻代中Eden(伊甸园)的容量 (字节)
  • EU 年轻代中Eden(伊甸园)目前已使用空间 (字节)
  • YGC 从应用程序启动到采样时年轻代中gc次
  • YGCT 从应用程序启动到采样时年轻代中gc所用时间(s)
jstat -gcnewcapacity<pid>:年轻代对象的信息及其占用量
  • NGCMN 年轻代(young)中初始化(最小)的大小(字节)
  • NGCMX 年轻代(young)的最大容量 (字节)
  • NGC 年轻代(young)中当前的容量 (字节)
  • S0CMX 年轻代中第一个survivor(幸存区)的最大容量 (字节)
  • S0C 年轻代中第一个survivor(幸存区)的容量 (字节)
  • S1CMX 年轻代中第二个survivor(幸存区)的最大容量 (字节)
  • S1C 年轻代中第二个survivor(幸存区)的容量 (字节)
  • ECMX 年轻代中Eden(伊甸园)的最大容量 (字节)
  • EC 年轻代中Eden(伊甸园)的容量 (字节)
  • YGC 从应用程序启动到采样时年轻代中gc次数
  • FGC 从应用程序启动到采样时old代(全gc)gc次数
jstat -gcold <pid>:old代对象的信息
  • PC Perm(持久代)的容量 (字节)
  • PU Perm(持久代)目前已使用空间 (字节)
  • OC Old代的容量 (字节)
  • OU Old代目前已使用空间 (字节)
  • YGC 从应用程序启动到采样时年轻代中gc次数
  • FGC 从应用程序启动到采样时old代(全gc)gc次数
  • FGCT 从应用程序启动到采样时old代(全gc)gc所用时间(s)
  • GCT 从应用程序启动到采样时gc用的总时间(s)
stat -gcoldcapacity <pid>: old代对象的信息及其占用量
  • OGCMN old代中初始化(最小)的大小 (字节)
  • OGCMX old代的最大容量(字节)
  • OGC old代当前新生成的容量 (字节)
  • OC Old代的容量 (字节)
  • YGC 从应用程序启动到采样时年轻代中gc次数
  • FGC 从应用程序启动到采样时old代(全gc)gc次数
  • FGCT 从应用程序启动到采样时old代(全gc)gc所用时间(s)
  • GCT 从应用程序启动到采样时gc用的总时间(s)
jstat –gcpermcapacity <pid>: perm对象的信息及其占用量
  • PGCMN perm代中初始化(最小)的大小 (字节)
  • PGCMX perm代的最大容量 (字节)
  • PGC perm代当前新生成的容量 (字节)
  • PC Perm(持久代)的容量 (字节)
  • YGC 从应用程序启动到采样时年轻代中gc次数
  • FGC 从应用程序启动到采样时old代(全gc)gc次数
  • FGCT 从应用程序启动到采样时old代(全gc)gc所用时间(s)
  • GCT 从应用程序启动到采样时gc用的总时间(s)
jstat -printcompilation <pid>:当前VM执行的信息
  • Compiled 编译任务的数目
  • Size 方法生成的字节码的大小
  • Type 编译类型
  • Method 类名和方法名用来标识编译的方法。类名使用/做为一个命名空间分隔符。方法名是给定类中的方法。上述格式是由-XX:+PrintComplation选项进行设置的

4、jmap:生成堆转储快照

jmap是JDK自带的工具软件,主要用于打印指定Java过程(或核心文件,远程调试服务器)的共享对象内存映射或堆内存细节。可以使用jmap生成堆转储。

  • 查看帮助:jmap -help
    在这里插入图片描述
    option参数详解:

  • <no option> 如果使用不带选项参数的jmap打印共享对象映射,将打印目标虚拟机中加载的每个共享对象的起始地址,映射大小以及共享对象文件的路径全称。

  • -dump:[live,]format=b,file=<filename> 以hprof二进制格式转储Java堆到指定filename的文件中。 live子选项是可选的。如果指定了live子选项,堆中只有活动的对象会被转储。想要浏览堆转储,你可以使用jhat (Java的堆分析工具)读取生成的文件。

  • -finalizerinfo 打印等待终结的对象信息。

  • -heap 打印一个堆的摘要信息,包括使用的GC算法,堆配置信息和代明智堆的使用情况。-histo[:live] 打印堆的柱状图。其中包括每一个Java类,对象数量,内存大小(单位:字节),完全限定的类名。打印的虚拟机内部的类名称将带有一个’*'替换。如果指定了live子选项,则只计算活动的对象。-permstat 打印的Java堆内存的永久保存区域的类加载器的智能统计信息。对于每个类加载器而言,它的名称 活跃度,地址,父类加载器,它所加载的类的数量和大小都会被打印。此外包含的字符串数量和大小也会被打印。

  • -F 强制模式。如果指定的PID没有响应,请使用JMAP -dump或jmap -histo选项。此模式下,不支持live子选项。

  • -h 打印帮助信息。

  • -help 打印帮助信息。

  • -J<flag> 指定传递给运行jmap的JVM的参数。

常用指令:

  • jmap -heap 31846 查看java堆(heap)使用情况
Attaching to process ID 31846, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 24.71-b01
 
using thread-local object allocation.
Parallel GC with 4 thread(s)//GC 方式
 
Heap Configuration: //堆内存初始化配置
MinHeapFreeRatio = 0 //对应jvm启动参数-XX:MinHeapFreeRatio设置JVM堆最小空闲比率(default 40)
MaxHeapFreeRatio = 100 //对应jvm启动参数-XX:MaxHeapFreeRatio设置JVM堆最大空闲比率(default 70)
MaxHeapSize  = 2082471936 (1986.0MB) //对应启动参数-XX:MaxHeapSize=设置JVM堆的最大大小
NewSize      = 1310720 (1.25MB)//对应jvm启动参数-XX:NewSize=设置JVM堆的‘新生代’的默认大小
MaxNewSize = 17592186044415 MB//对应jvm启动参数-XX:MaxNewSize=设置JVM堆的‘新生代’的最大大小
OldSize  = 5439488 (5.1875MB)//对应jvm启动参数-XX:OldSize=<value>:设置JVM堆的‘老生代’的大小
NewRatio  = 2 //对应jvm启动参数-XX:NewRatio=:‘新生代’和‘老生代’的大小比率
SurvivorRatio = 8 //对应jvm启动参数-XX:SurvivorRatio=设置年轻代中Eden区与Survivor区的大小比值
PermSize = 21757952 (20.75MB)  //对应jvm启动参数-XX:PermSize=<value>:设置JVM堆的‘永生代’的初始大小
MaxPermSize      = 85983232 (82.0MB)//对应jvm启动参数-XX:MaxPermSize=<value>:设置JVM堆的‘永生代’的最大大小
G1HeapRegionSize = 0 (0.0MB)
 
Heap Usage://堆内存使用情况
PS Young Generation
Eden Space://Eden区内存分布
   capacity = 33030144 (31.5MB)//Eden区总容量
   used     = 1524040 (1.4534378051757812MB)  //Eden区已使用
   free     = 31506104 (30.04656219482422MB)  //Eden区剩余容量
   4.614088270399305% used //Eden区使用比率
From Space:  //其中一个Survivor区的内存分布
   capacity = 5242880 (5.0MB)
   used     = 0 (0.0MB)
   free     = 5242880 (5.0MB)
   0.0% used
To Space:  //另一个Survivor区的内存分布
   capacity = 5242880 (5.0MB)
   used     = 0 (0.0MB)
   free     = 5242880 (5.0MB)
   0.0% used
PS Old Generation //当前的Old区内存分布
   capacity = 86507520 (82.5MB)
   used     = 0 (0.0MB)
   free     = 86507520 (82.5MB)
   0.0% used
PS Perm Generation//当前的“永生代” 内存分布
   capacity = 22020096 (21.0MB)
   used     = 2496528 (2.3808746337890625MB)
   free     = 19523568 (18.619125366210938MB)
   11.337498256138392% used
 
670 interned Strings occupying 43720 bytes.
  • jmap -histo 3331:查看堆内存(直方图)中的对象数量及大小。
 #num      #instances       #bytes           #class name
  编号          个数            字节                类名
----------------------------------------------------------------
   1:           7            1322080              [I
   2:          5603           722368         <methodKlass>
   3:          5603           641944       <constMethodKlass>
   4:         34022           544352       java.lang.Integer
   5:           371           437208       <constantPoolKlass>
   6:           336           270624    <constantPoolCacheKlass>
   7:           371           253816      <instanceKlassKlass>
  • jmap -dump:format=b,file=heapDump 6900 将要使用的内存的详细情况输出到文件

然后用jhat命令可以参见jhat -port 5000 heapDump在浏览器中访问:http://localhost:5000/查看详细信息
 
这个命令执行,JVM重新整堆堆的信息转储写入一个文件,堆如果比较大的话,就会导致这个过程比较耗时,并且执行的过程中为了保证转储的信息是可靠的,所以会暂停应用。

总结:

  1. 如果程序内存不足或经常GC,很有可能存在内存不足情况,这时候就要重新使用Java堆Dump查看对象的情况
  2. 要制作堆Dump可以直接使用jvm自带的jmap命令
  3. 可以先使用jmap -heap命令查看堆的使用情况,看一下各个堆空间的占用情况。
  4. 使用jmap -histo:[live]查看堆内存中的对象的情况。如果有大量对象在持续被引用,并没有被释放掉,那就产生了内存泄露,就要结合代码,把不用的对象释放掉。
  5. 可以使用jmap -dump:format=b,file=<fileName>命令将堆信息保存到一个文件中,再借助与jhat命令查看详细内容
  6. 在内存出现泄露,溢出或者其它前提条件下,建议多转储先前的内存,把内存文件进行编号扩展,并进行后续的内存整理分析。

5、jhat:Java堆分析工具

jhat(Java堆分析工具),是一个用来分析java的堆情况的命令。使用jmap可以生成Java堆的Dump文件。生成转储文件之后就可以用jhat命令,将转储文件转成html的形式,然后通过http访问可以查看堆情况。

jhat命令解析会Java堆dump并启动一个web服务器,然后就可以在浏览器中查看堆的dump文件了。

  • 使用 jhat -help 查看帮助
    在这里插入图片描述
    使用步骤:
  • 1.查看该进程的ID
jps  //使用jps命令查看JAVA进程ID
  • 2.生成转储文件
jmap -dump:format=b,file=heapDump 62247
  • 3.解析Java堆转储文件,并启动一个Web服务器
jhat heapDump
  • 使用jhat命令,就启动了一个http服务,端口是7000,然后在访问 http://localhost:7000/,就可以在浏览器中查看堆的dump文件了。

常用命令:

  • jmap -dump:format=b,file=heapDump 3331 + jhat heapDump:生成并解析Java堆转储文件,并启动一个 web server

6、jstack:堆栈跟踪工具

jstack是java虚拟机自带的一种堆栈跟踪工具

jstack用于生成java虚拟机当前时刻的线程快照。线程快照是当前java虚拟机内每一条线程正在执行的方法堆栈的集合,生成线程快照的主要目的是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待等。线程出现停顿的时候通过jstack来查看各个线程的调用堆栈,就可以知道没有响应的线程到底在后台做什么事情,或者等待什么资源。 如果java程序崩溃生成core文件,jstack工具可以用来获得core文件的java stack和native stack的信息,从而可以轻松地知道java程序是如何崩溃和在程序何处发生问题。另外,jstack工具还可以附属到正在运行的java程序中,看到当时运行的java程序的java stack和native stack的信息, 如果现在运行的java程序呈现hung的状态,jstack是非常有用的。

拓展知识:

  • 线程状态
    想要通过jstack命令来分析线程的情况的话,首先要知道线程都有哪些状态,下面这些状态是我们使用jstack命令查看线程堆栈信息时可能会看到的线程的几种状态:

NEW,未启动的。不会出现在Dump中。
RUNNABLE,在虚拟机内执行的。 BLOCKED,受阻塞并等待监视器锁。
WATING,无限期等待另一个线程执行特定操作。
TIMED_WATING,有时限的等待另一个线程的特定操作。
TERMINATED,已退出的。

  • 调用修饰
    表示线程在方法调用时,额外的重要的操作。线程Dump分析的重要信息。修饰上方的方法调用。

locked <地址> 目标:使用synchronized申请对象锁成功,监视器的拥有者。
waiting to lock <地址>目标:使用synchronized申请对象锁未成功,在迚入区等待。 waiting on <地址>目标:使用synchronized申请对象锁成功后,释放锁幵在等待区等待。
parking to wait for <地址> 目标:需与堆栈中的"parking to wait for (at java.util.concurrent.SynchronousQueue$TransferStack)"结合来看。first–>此线程是在等待某个条件的发生,来把自己唤醒,second–>SynchronousQueue不是一个队列,其是线程之间移交信息的机制,当我们把一个元素放入到 SynchronousQueue 中时必须有另一个线程正在等待接受移交的任务,因此这就是本线程在等待的条件。

• 常用指令

jstack 3331:查看线程情况
jstack -F 3331:正常输出不被响应时,使用该指令
jstack -l 3331:除堆栈外,显示关于锁的附件信息

二:通过Java命令排查问题

试题1:某服务器CPU使用率达到99%,排查是哪个程序的哪个线程导致的高CPU

思路:

  1. 先找到耗CPU高的进程;
  2. 找到耗CPU高的线程;
  3. 找到耗CPU高的线程对应的业务代码;

操作:

1.1、执行“top -c”命令,显示进程运行信息列表,键入大写P,按CPU使用率降序排列:
在这里插入图片描述

1.2、获取到进程PID为10765的进程,使用CPU资源最高19.9%;
至此,已找到耗CPU最高的进程,进程PID为10765,后续命令中需要使用到。

2.1、一个进程内有很多线程,执行“top -Hp 10765”,显示进程ID为10765的线程列表,键入大写P,按CPU使用率降序排列:
在这里插入图片描述

2.2、其中,PID为10804的线程,CPU使用率最高2.3%;
2.3、将线程ID(10804)按16进制展示,执行指令“printf "%x\n" 10804”:
至此,找到了CPU使用率最高的线程ID为10804,并获取到10804的16进制标识:2a34

(转为16进制,是因为jstack打印出的线程栈信息中,线程id是通过16进制展示的)

3.1、通过jstack检索到进程(进程ID=10765)中,最耗CPU的线程(线程ID=2a34)的线程栈信息;
执行指令“jstack 10765 | grep "2a34" -C5 --color”:

C5:打印当前这一行的以及前后5行信息
color:将2a34明显起来(加粗)
在这里插入图片描述

至此,找到了耗CPU高的线程对应的线程名称“AsyncLogger-1”,而这个线程名称是我们业务代码中给线程取的名称,可以快速定位到业务代码。
tips:给线程取一个与业务处理相关的名称,对快速定位问题尤为重要。
如果我们没有给线程取名称“AsyncLogger-1”,那打印出来的线程名称可能是:
在这里插入图片描述

通过不知名的线程名称“pool-5-thread-1”,以及只包含jdk代码的线程栈信息,我们无法定位到业务代码。

试题2:某java应用大量消耗内存,导致OutOfMemoryError

思路:

  1. 什么对象消耗内存最大;
  2. 是否创建了太多的线程;
  3. 新生的、老年代现在内存使用情况,确认是不是整体内存分配太小了;
  4. 实时查看新生的、老年代内存使用情况,GC情况
  5. 代码层检查,是否有大对象创建?需要调用close()或dispose()来回收的资源是否回收了?

操作:

1、执行“jmap -histo:live 10765 | more”命令,以表格的方式显示存活对象的信息(已按对象所占bytes大小进行降序排列):
其中,10765为进程ID,更多用法,通过“man jmap”寻求帮助。
在这里插入图片描述

占内存最多的对象类型是org.apache.logging.log4j.core.async.RingBufferLogEvent,
总共18874368byte (18M),例子中属于正常使用。

tips:如果发现某类对象占用内存很大(几个G的大小),很可能是有问题的。

基本都是因为:该类对象创建太多,且一直未释放。比如:使用完IO资源后,未调用close()接口关闭、释放资源;又比如:消费者消费速度慢(或停止消费了),而生产者不断往队列中投递任务,导致队列中任务累积过多,任务对象占用内存太多而产生OutOfMemoryError

2、执行“pstree -p 10765 | wc -l”,查看进程内的线程数
其中,10765为进程ID。
每个线程需要分配线程栈内存,创建线程太多,可能导致OutOfMemoryError。

3、执行“jmap -heap 10765”,查看堆(新生代、老年代)内存分配大小及使用情况
在这里插入图片描述

4、执行“jstat -gc 10765 1000”,查看各个区内存使用情况及GC情况
其中,10765为进程ID,1000为数据刷新间隔的毫秒数
在这里插入图片描述

具体字段含义,通过“man jstat”寻求帮助。
主要查看:

  • EC:Eden区容量,
  • EU:Eden区已使用量,
  • OC:Old区容量,
  • OU:Old区已使用量;
  • YGC:YongGC次数,
  • YGCT:YongGC耗时,
  • FGC:FullGC次数,
  • FGCT:FullGC耗时;

5、代码检查,要求相关同学做codereview(代码评审)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值