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<lines>] 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:
    <none>  如果不使用任何选项,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. 
    

    <!== 创建堆dump文件 ==>

    $ 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命令分析堆dump文件 ==>

    $ 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 <pid>
      #结果保存截图
      
    2. 打印线程堆栈信息到文件

      $ jstack -l <pid> > <filename>
      
    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:
    <none>  打印命令行参数和系统属性名称-值对
    -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 持有的内存空间。

©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,482评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,377评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,762评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,273评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,289评论 5 373
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,046评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,351评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,988评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,476评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,948评论 2 324
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,064评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,712评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,261评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,264评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,486评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,511评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,802评论 2 345

推荐阅读更多精彩内容