JVM

一、JVM监控及排查分析命令详解

1、jps

JVM Process Status Tool,用于显示指定系统内所有的HotSpot虚拟机进程。

usage: jps [options] [hostid]     #hostid可以省略

options:
    -l  显示pid和应用程序main class的完整包名或者应用程序的jar路径
    -q  只显示 pid
    -m  显示pid、应用程序main class类名和传递给main方法的参数,在嵌入式jvm上可能是null
    -v  显示pid、应用程序main class类名和传递给jvm的参数
    -V  默认,显示pid和应用程序main class类名

2、jstat

JVM statistics Monitoring是用于监视虚拟机运行时状态信息的命令,它可以显示出虚拟机进程中的类装载、内存、垃圾收集、JIT编译(Just In Time Compiler, 即时编译器)等运行数据。

usage: jstat [option] [-t] [-h] LVMID [interval] [count]
    [interval]: 连续输出的时间间隔
    [count]: 输出的次数

options:
    -class  显示有关类加载器行为的统计信息
    -compiler  显示有关Java HotSpot VM即时编译器行为的统计信息。
    -gc  显示有关垃圾收集堆行为的统计信息。
    -gccapacity  显示各个垃圾回收代容量及其对应空间的统计信息。
    -gccause  显示有关垃圾收集统计信息的摘要(与 -gcutil 相同),以及最后和当前(如果适用)垃圾收集事件的原因。
    -gcnew  显示新生代行为的统计信息。
    -gcnewcapacity  显示有关新生代及其对应空间大小的统计信息。
    -gcold  显示有关老年代行为的统计信息和元空间统计信息。
    -gcoldcapacity  显示有关老年代大小的统计信息。
    -gcmetacapacity  显示有关元空间大小的统计信息。
    -gcutil  显示有关垃圾收集统计信息的摘要。
    -printcompilation  显示Java HotSpot VM编译方法统计信息。


-t:将时间戳列显示为输出的第一列。时间戳是自目标JVM启动时间以来的时间。
-h n:每n个样本(输出行)显示一个列标题,其中n是一个正整数。默认值为0,即显示列标题的第一行数据。
  • -class标题字段含义

    Loaded:加载class的数量

    Bytes:加载class占用大小(KB)

    Unloaded:未加载class的数量

    Bytes:未加载class占用大小(KB)

    Time:执行加载class和卸载class操作所花费的时间

  • -compiler标题字段含义

    Compiled:执行的编译任务数

    Failed:执行失败的编译任务数

    Invalid:无效的编译任务数

    Time:执行编译任务所花费的时间

    FailedType:上次编译失败的编译类型

    FailedMethod:上次失败编译的类名和方法

  • -gc标题字段含义

    S0C:survivor0空间当前容量(KB)

    S1C:survivor1空间当前容量(KB)

    S0U:survivor0空间利用容量(KB)

    S1U:survivor1空间利用容量(KB)

    EC:Eden空间当前容量(KB)

    EU:Eden空间利用容量(KB)

    OC:Old空间当前容量(KB)

    OU:Old空间利用容量(KB)

    MC:元空间容量(KB)

    MU:元空间利用容量(KB)

    CCSC:压缩类空间容量(KB)

    CCSU:压缩类空间已使用容量(KB)

    YGC:年轻代垃圾回收次数

    YGCT:年轻代垃圾回收时间

    FGC:full gc次数

    FGCT:full gc耗时

    GCT:总垃圾回收时间

  • -gccapacity标题字段含义

    NGCMN:最小new generation容量(KB),近似年轻代

    NGCMX:最大new generation容量(KB),近似年轻代

    NGC:new generation容量(KB),近似年轻代

    OGCMN:最小老年代容量(KB)

    OGCMX:最大老年代容量(KB)

    OGC:老年代容量(KB)

    MCMN:最小元空间容量(KB)

    MCMX:最大元空间容量(KB)

    CCSMN:压缩类空间最小容量(KB)

    CCSMX:压缩类空间最大容量(KB)

  • -gccause标题字段含义

    S0:survivor0空间利用容量占当前容量的百分比

    S1:survivor1空间利用容量占当前容量的百分比

    E:Eden空间利用容量占当前容量的百分比

    O:Old空间利用容量占当前容量的百分比

    M:元空间利用容量占当前容量的百分比

    CCS:压缩类空间利用率百分比

    YGC:年轻代垃圾回收次数

    YGCT:年轻代垃圾回收时间

    FGC:full gc次数

    FGCT:full gc耗时

    GCT:总垃圾回收时间

    LGCC:上次垃圾回收的原因

    GCC:当前垃圾回收的原因

  • -gcutil标题字段含义

    -gccause标题字段含义一致

  • -gcnew标题字段含义

    TT:晋升阈值

    MTT:最大晋升阈值

    DSS:所需survivor空间大小(KB)

  • -gcnewcapacity标题字段含义

    S0CMX:最大survivor0空间容量(KB)

    S1CMX:最大survivor1空间容量(KB)

    ECMX:最大Eden空间容量(KB)

  • -gcold标题字段含义

    该字段含义在上文中都有

  • -gcoldcapacity标题字段含义

    该字段含义在上文中都有

  • -gcmetacapacity标题字段含义

    该字段含义在上文中都有

  • -printcompilation标题字段含义

    Compiled:最近执行的编译方法任务数

    Size:最近编译方法的字节码的数量

    Type:最近编译的方法的编译类型

    Method:标识最近编译的方法的类名和方法名。方法名是指定类中的方法。

3、jmap

打印进程、核心文件或远程调试服务器的共享对象内存映射或堆内存详细信息。

除此命令外,通过指定-XX:+HeapDumpOnOutOfMemoryError参数,在发生OutOfMemoryError时生成堆dump文件。或者使用hprof命令也可以生成。

usage: jmap [ options ] pid
       jmap [ options ] executable core
       jmap [ options ] [ pid ] server-id@ ] remote-hostname-or-IP
    executable:生成可执行的核心转储文件
    core:打印内存映射的核心文件
    remote-hostname-or-IP:远程调试服务器主机名或IP地址
    server-id:当多个调试服务器在同一远程主机上运行时使用的可选唯一ID

options:
      如果不使用任何选项,jmap命令会打印共享对象映射。对于目标JVM中加载的每个共享对象,都会打印共享对象文件的起始地址、映射大小和完整路径
    -dump:[live,] format=b, file=filename
        以hprof二进制格式生成堆转储文件。live子选项是可选的,当指定时,仅转储堆中的活动对象。要浏览堆转储文件,可以使用jhat命令读取。
    -finalizerinfo  打印有关等待回收的对象的信息
    -heap  打印堆的概要信息,包括GC、head configuration、generation-wise heap usage等
    -histo[:live]  打印堆的对象统计,包括对象数、内存大小等等
    -clstats  打印堆的类加载器统计信息。
    -F  强制。当pid没有反应时,将这个选项与jmap -dump或jmap -histo选项一起使用。在这种模式下不支持live子选项。
    -Jflag  将flag传递给运行jmap命令的Java虚拟机。

description:
    jmap命令打印指定进程、核心文件或远程调试服务器的共享对象内存图或堆内存细节。
    如果指定的进程在64位Java虚拟机(JVM)上运行,那么你可能需要指定-J-d64选项,例如:jmap -J-d64 -heap pid。
  • 示例

    $ jmap -finalizerinfo 30809
    Attaching to process ID 30809, please wait...
    Debugger attached successfully.
    Server compiler detected.
    JVM version is 25.251-b08
    Number of objects pending for finalization: 0
    

    $ jmap -heap 30809
    Attaching to process ID 30809, please wait...
    Debugger attached successfully.
    Server compiler detected.
    JVM version is 25.251-b08
    
    using thread-local object allocation.
    Parallel GC with 4 thread(s)   //GC方式
    
    Heap Configuration:   //堆内存初始化配置,对应jvm启动参数
       MinHeapFreeRatio         = 0
       MaxHeapFreeRatio         = 100
       MaxHeapSize              = 1073741824 (1024.0MB)
       NewSize                  = 357564416 (341.0MB)
       MaxNewSize               = 357564416 (341.0MB)
       OldSize                  = 716177408 (683.0MB)
       NewRatio                 = 2
       SurvivorRatio            = 8
       MetaspaceSize            = 268435456 (256.0MB)
       CompressedClassSpaceSize = 528482304 (504.0MB)
       MaxMetaspaceSize         = 536870912 (512.0MB)
       G1HeapRegionSize         = 0 (0.0MB)
    
    Heap Usage:  //堆内存使用情况
    PS Young Generation  //年轻代使用情况
    Eden Space:  //Eden区内存情况
       capacity = 353370112 (337.0MB)
       used     = 198190016 (189.00872802734375MB)
       free     = 155180096 (147.99127197265625MB)
       56.08567597250556% used
    From Space:  //其中一个Survivor区的内存情况
       capacity = 2097152 (2.0MB)
       used     = 1006928 (0.9602813720703125MB)
       free     = 1090224 (1.0397186279296875MB)
       48.014068603515625% used
    To Space:  //其中一个Survivor区的内存情况
       capacity = 2097152 (2.0MB)
       used     = 0 (0.0MB)
       free     = 2097152 (2.0MB)
       0.0% used
    PS Old Generation  //老年代内存情况
       capacity = 716177408 (683.0MB)
       used     = 62305128 (59.418800354003906MB)
       free     = 653872280 (623.5811996459961MB)
       8.699677943485199% used
    
    37015 interned Strings occupying 4020168 bytes.
    

    $ jmap -F -histo 30809
    Attaching to process ID 30809, please wait...
    Debugger attached successfully.
    Server compiler detected.
    JVM version is 25.251-b08
    Iterating over heap. This may take a while...
    Object Histogram:
    
    num       #instances    #bytes  Class description
    --------------------------------------------------------------------------
    1:              183560  22797768        char[]
    2:              1395    4765360 long[]
    3:              15811   4545944 byte[]
    4:              181047  4345128 java.lang.String
    5:              41490   3651120 java.lang.reflect.Method
    6:              23943   3640280 int[]
    7:              107354  3435328 java.util.concurrent.ConcurrentHashMap$Node
    8:              49566   3015984 java.lang.Object[]
    9:              18664   2068768 java.lang.Class
    10:             34349   1373960 java.util.LinkedHashMap$Entry
    ...
    Total :         1176270 67035968
    Heap traversal took 47.908 seconds. 
    

    $ jmap -dump:format=b,file=/tmp/cus-operation-server.hprof 30809
    Attaching to process ID 30809, please wait...
    Debugger attached successfully.
    Server compiler detected.
    JVM version is 25.251-b08
    Dumping heap to /tmp/cus-operation-server.hprof ...
    Heap dump file created
    

    $ jhat -J-Xmx2048m cus-operation-server.hprof 
    Reading from cus-operation-server.hprof...
    Dump file created Fri Apr 22 11:34:22 CST 2022
    Snapshot read, resolving...
    Resolving 5178821 objects...
    WARNING: Class c31ed980 not found, adding fake class!
    WARNING: Class c1feb088 not found, adding fake class!
    WARNING: Class c03bda70 not found, adding fake class!
    WARNING: Class c03bdaf0 not found, adding fake class!
    WARNING: Class c0847af0 not found, adding fake class!
    WARNING: Class c324d1b8 not found, adding fake class!
    WARNING: Class c03bc090 not found, adding fake class!
    WARNING: Class c03bc110 not found, adding fake class!
    WARNING: Class c03bc190 not found, adding fake class!
    WARNING:  Failed to resolve object id 0xc08089f0 for field clazz (signature L)
    WARNING:  Failed to resolve object id 0xc0808750 for field clazz (signature L)
    WARNING:  Failed to resolve object id 0xc08083c8 for field clazz (signature L)
    WARNING:  Failed to resolve object id 0xc0808128 for field clazz (signature L)
    WARNING:  Failed to resolve object id 0xc0807e90 for field clazz (signature L)
    Chasing references, expect 1035 dots...........................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
    Eliminating duplicate references...........................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
    Snapshot resolved.
    Started HTTP server on port 7000
    Server is ready. 
    

    登录web页面使用OQL进行查询分析

    主页面
    oql查询页面
oql语句帮助页面

4、jstack

打印 Java 进程、核心文件或远程调试服务器的 Java 线程堆栈跟踪。

usage: jstack [ options ] pid
       jstack [ options ] executable core
       jstack [ options ] [ server-id@ ] remote-hostname-or-IP
    executable:生成可执行的核心转储文件
    core:打印内存映射的核心文件
    remote-hostname-or-IP:远程调试服务器主机名或IP地址
    server-id:当多个调试服务器在同一远程主机上运行时使用的可选唯一ID

options:
    -F  当jstack [-l] pid没有反应时,强制进行堆栈转储
    -l  打印关于锁的额外信息
    -m  打印一个混合模式的堆栈跟踪,其中有Java和本地C/C++框架,该选项不适用于远程调试服务器

description:
    jstack命令打印指定的Java进程、核心文件或远程调试服务器的Java线程的堆栈痕迹。对于每个Java框架,如果有的话,会打印完整的类名、方法名、字节码索引(BCI)和行号。当指定的进程在64位Java虚拟机上运行时,你可能需要指定-J-d64选项,例如:jstack -J-d64 -m pid。
    
  • 示例

    cpu异常问题排查步骤

    1. 使用top命令查看程序cpu占用率过高的线程

      $ top -Hp 
      #结果保存截图
      
    2. 打印线程堆栈信息到文件

      $ jstack -l  > 
      
    3. 将步骤1中的占用cpu过高的TID转换成16进制

      $ printf "%x\n" TID
      
    4. 在堆栈文件中搜索对应TID

5、jinfo

生成配置信息,实时查看和调整虚拟机运行参数。

usage: jinfo [ option ] pid
       jinfo [ option ] executable core
       jinfo [ option ] [ servier-id ] remote-hostname-or-IP
    executable:生成可执行的核心转储文件
    core:打印内存映射的核心文件
    remote-hostname-or-IP:远程调试服务器主机名或IP地址
    server-id:当多个调试服务器在同一远程主机上运行时使用的可选唯一ID


options:
      打印命令行参数和系统属性名称-值对
    -flag name  打印指定命令行参数的名称和值
    -flag [+|-]name  启用或禁用指定的布尔值命令行参数
    -flag name=value  将指定的命令行参数设置为指定的值
    -flags  打印传递给JVM的命令行参数
    -sysprops  将Java系统属性打印为名称-值对

description:
    jinfo命令打印指定Java进程或核心文件或远程调试服务器的Java配置信息。配置信息包括Java系统属性和JVM命令行标志。如果指定的进程在64位JVM上运行,那么您可能需要指定-J-d64选项,例如:jinfo -J-d64 -sysprops pid。
  • 示例

    $ jinfo 30809
    Attaching to process ID 30809, please wait...
    Debugger attached successfully.
    Server compiler detected.
    JVM version is 25.251-b08
    Java System Properties:
    
    com.sun.management.jmxremote.authenticate = false
    java.runtime.name = Java(TM) SE Runtime Environment
    java.vm.version = 25.251-b08
    sun.boot.library.path = /data/svr/jdk1.8.0_251/jre/lib/amd64
    java.protocol.handler.pkgs = org.springframework.boot.loader
    apollo.cluster = dev
    java.vendor.url = http://java.oracle.com/
    java.vm.vendor = Oracle Corporation
    path.separator = :
    java.rmi.server.randomIDs = true
    file.encoding.pkg = sun.io
    java.vm.name = Java HotSpot(TM) 64-Bit Server VM
    sun.os.patch.level = unknown
    sun.java.launcher = SUN_STANDARD
    user.country = US
    ...
    
    VM Flags:
    Non-default VM flags: -XX:AutoBoxCacheMax=20000 -XX:CICompilerCount=3 -XX:CompressedClassSpaceSize=528482304 -XX:GCLogFileSize=1048576 -XX:+HeapDumpOnOutOfMemoryError -XX:InitialHeapSize=1073741824 -XX:+ManagementServer -XX:MaxHeapSize=1073741824 -XX:MaxMetaspaceSize=536870912 -XX:MaxNewSize=357564416 -XX:MetaspaceSize=268435456 -XX:MinHeapDeltaBytes=524288 -XX:NewSize=357564416 -XX:NumberOfGCLogFiles=10 -XX:OldSize=716177408 -XX:+PrintGC -XX:+PrintGCApplicationStoppedTime -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps -XX:+UseGCLogFileRotation -XX:+UseParallelGC 
    Command line:  -Xms1024m -Xmx1024m -XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=512M -XX:+HeapDumpOnOutOfMemoryError -XX:AutoBoxCacheMax=20000 -Xloggc:/dev/shm/gc-fbg-il8n-server.log -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:+PrintGCApplicationStoppedTime -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=1M -Djava.rmi.server.hostname=10.81.48.30 -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=50606 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Dapp.name=fbg-il8n-server -Dapp.repo=/data/local/apps/fbg-il8n-server/lib -Dapp.home=/data/local/apps/fbg-il8n-server -Dbasedir=/data/local/apps/fbg-il8n-server
    

    #需要以程序运行用户执行
    $ jinfo -flag MaxMetaspaceSize 30809
    -XX:MaxMetaspaceSize=536870912
    

    $ jinfo -flag MaxHeapFreeRatio=65 30809
    $ jinfo -flags 30809
    Attaching to process ID 30809, please wait...
    Debugger attached successfully.
    Server compiler detected.
    JVM version is 25.251-b08
    Non-default VM flags: -XX:AutoBoxCacheMax=20000 -XX:CICompilerCount=3 -XX:CompressedClassSpaceSize=528482304 -XX:GCLogFileSize=1048576 -XX:+HeapDumpOnOutOfMemoryError -XX:InitialHeapSize=1073741824 -XX:+ManagementServer -XX:MaxHeapFreeRatio=65 -XX:MaxHeapSize=1073741824 -XX:MaxMetaspaceSize=536870912 -XX:MaxNewSize=357564416 -XX:MetaspaceSize=268435456 -XX:MinHeapDeltaBytes=524288 -XX:NewSize=357564416 -XX:NumberOfGCLogFiles=10 -XX:OldSize=716177408 -XX:+PrintGC -XX:+PrintGCApplicationStoppedTime -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps -XX:+UseGCLogFileRotation -XX:+UseParallelGC 
    Command line:  -Xms1024m -Xmx1024m -XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=512M -XX:+HeapDumpOnOutOfMemoryError -XX:AutoBoxCacheMax=20000 -Xloggc:/dev/shm/gc-fbg-il8n-server.log -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:+PrintGCApplicationStoppedTime -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=1M -Djava.rmi.server.hostname=10.81.48.30 -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=50606 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Dapp.name=fbg-il8n-server -Dapp.repo=/data/local/apps/fbg-il8n-server/lib -Dapp.home=/data/local/apps/fbg-il8n-server -Dbasedir=/data/local/apps/fbg-il8n-server 
    
    #支持动态修改的参数
    $ java -XX:+PrintFlagsInitial | grep manageable
         intx CMSAbortablePrecleanWaitMillis            = 100                                 {manageable}
         intx CMSTriggerInterval                        = -1                                  {manageable}
         intx CMSWaitDuration                           = 2000                                {manageable}
         bool HeapDumpAfterFullGC                       = false                               {manageable}
         bool HeapDumpBeforeFullGC                      = false                               {manageable}
         bool HeapDumpOnOutOfMemoryError                = false                               {manageable}
        ccstr HeapDumpPath                              =                                     {manageable}
        uintx MaxHeapFreeRatio                          = 70                                  {manageable}
        uintx MinHeapFreeRatio                          = 40                                  {manageable}
         bool PrintClassHistogram                       = false                               {manageable}
         bool PrintClassHistogramAfterFullGC            = false                               {manageable}
         bool PrintClassHistogramBeforeFullGC           = false                               {manageable}
         bool PrintConcurrentLocks                      = false                               {manageable}
         bool PrintGC                                   = false                               {manageable}
         bool PrintGCDateStamps                         = false                               {manageable}
         bool PrintGCDetails                            = false                               {manageable}
         bool PrintGCID                                 = false                               {manageable}
         bool PrintGCTimeStamps                         = false                               {manageable}
    

二、常见JVM内存错误问题排查

1、Java heap space

当堆内存(Heap Space)没有足够空间存放新创建的对象时,就会抛出java.lang.OutOfMemoryError: Java heap space 错误。

  • 原因分析

    1. 请求创建一个超大对象

    2. 超出预期的访问量/数据量,通常是上游系统请求流量飙升,常见于各类促销/秒杀活动,可以结合业务流量指标排查是否有尖状峰值。

    3. 过度使用终结器(Finalizer),该对象没有立即被GC.

    4. 内存泄漏(Memory Leak),大量对象引用没有释放,JVM无法对其自动回收,常见于使用了File等资源没有回收。

  • 解决方案

    首先使用jmap -dump:format=b,file=FILE_WITH_PATH PID 命令生成dump文件已变后续分析, 再通过-Xmx参数调高 JVM 堆内存空间重启服务(临时解决)。如果是超大对象,可以检查其合理性,比如是否一次性查询了数据库全部结果,而没有做结果数限制。如果是业务峰值压力,可以考虑添加机器资源,或者做限流降级。如果是内存泄漏,需要找到持有的对象,修改代码设计,比如关闭没有释放的连接。

2、GC overhead limit exceeded

当Java进程花费98%以上的时间执行GC,但只恢复了不到2%的内存,且该动作连续重复了5次,就会抛出java.lang.OutOfMemoryError: GC overhead limit exceeded 错误。简单地说,就是应用程序已经基本耗尽了所有可用内存,GC也无法回收。

此类问题的原因与解决方案跟 Java heap space 非常类似,可以参考上文。

3、Permgen space

java.lang.OutOfMemoryError: Permgen space该错误表示永久代(Permanent Generation)已用满。

  • 原因分析

    通常是因为加载的class数目太多或体积太大。PermGen的使用量与加载到内存的class的数量/大小成正相关。

  • 解决方案

    根据 Permgen space 报错的时机,可以采用不同的解决方案:

    1. 程序启动报错,修改-XX:MaxPermSize启动参数,调大永久代空间。

    2. 应用重新部署时报错,很可能是没有应用没有重启,导致加载了多份 class 信息,只需重启 JVM 即可解决。

    3. 运行时报错,应用程序可能会动态创建大量class,而这些class的生命周期很短暂,但是JVM默认不会卸载class,可以设置-XX:+CMSClassUnloadingEnabled-XX:+UseConcMarkSweepGC这两个参数允许JVM卸载class。

    上述方法无法解决,可以通过jmap -dump:format=b,file=FILE_WITH_PATH PID命令生成dump文件,然后利用Eclipse MAT软件功能逐一分析开销最大的classloader和重复class。

4、Metaspace

JDK 1.8使用Metaspace(元空间)替换了永久代(Permanent Generation),java.lang.OutOfMemoryError: Metaspace该错误表示Metaspace已被用满。

此类问题的原因与解决方法跟Permgen space非常类似,可以参考上文。需要特别注意的是调整Metaspace空间大小的启动参数为 -XX:MaxMetaspaceSize

5、Unable to create new native thread

每个Java线程都需要占用一定的内存空间,当JVM向底层操作系统请求创建一个新的native线程时,如果没有足够的资源分配就会报此类错误java.lang.OutOfMemoryError: Unable to create new native thread

  • 原因分析

    1. 线程数超过操作系统最大线程数ulimit限制。

    2. 线程数超过kernel.pid_max(只能重启)。

    3. 本机内存不足。

  • 解决方案

    • 升级服务器内存资源

    • 降低 Java Heap Space 大小

    • 修复应用程序的线程泄漏问题

    • 限制线程池大小

    • 使用-Xss参数减少线程栈的大小

    • 调高OS层面的线程最大数:使用ulimit -u xxx 命令调整最大线程数限制。

6、Out of swap space?

java.lang.OutOfMemoryError: Out of swap space?该错误表示所有可用的虚拟内存已被耗尽。虚拟内存(Virtual Memory)由物理内存(Physical Memory)和交换空间(Swap Space)两部分组成。当运行时程序请求的虚拟内存溢出时就会报 Out of swap space? 错误。

  • 原因分析

    1. 主机虚拟内存耗尽

    2. 应用程序的本地内存泄漏(native leak)

  • 解决方案

    升级服务器内存资源

7、Direct buffer memory

DirectByteBuffer顾名思义直接缓冲,我们可以使用它进行堆外内存的分配/使用/回收。DirectByteBuffer晋升到老年代,必须要等到full gc 才有可能被回收。当DirectByteBuffer使用较多且存活时间过长的情况时,则可能造成堆外内存OOM出现java.lang.OutOfMemoryError: Direct buffer memory错误

  • 原因分析

    1. 通过 ByteBuffer.allocateDirect 方法使用Direct ByteBuffer,该方法是分配堆外内存,不属于GC管辖范围,由于不需要内存拷贝所以速度相对较快。但如果不断分配堆外内存,堆内存很少使用,那么JVM就不需要进行GC,DirectByteBuffer对象们就不会被回收。这个时候堆内存充足,但堆外内存可能已经耗尽。

    2. Direct ByteBuffer使用值超过最大上限

  • 解决方案

    1. 通过启动参数-XX:MaxDirectMemorySize调整 Direct ByteBuffer 的上限值。

    2. 去掉启动参数-XX:+DisableExplicitGC ,该参数会使 System.gc() 失效。

    3. 检查堆外内存使用代码,确认是否存在内存泄漏;或者通过反射调用 sun.misc.Cleaner 的 clean() 方法来主动释放被 Direct ByteBuffer 持有的内存空间。

你可能感兴趣的:(JVM)