記一個有趣的Java OOM!

本文首發於我的微信公衆號《andyqian》,期待你的關注~

引言

  熟悉Java的童鞋,應該對OOM比較熟悉。該類問題,通常都比較棘手。由於形成此類問題的緣由有不少。今天就分享一個很是有意思的案例。(說實話。這個問題,我也是前兩天才遇到的。花了很多時間來分析。以爲很是有意思,記錄在此。大神勿噴!)java

問題場景

重啓應用時,調試到給MQ發消息時。有以下錯誤:apache

Exception in thread "Thread-4" java.lang.OutOfMemoryError: unable to create new native thread
    at java.lang.Thread.start0(Native Method)
    at java.lang.Thread.start(Thread.java:717)
    at java.util.concurrent.ThreadPoolExecutor.addWorker(ThreadPoolExecutor.java:957)
    at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1378)
    at org.apache.activemq.thread.PooledTaskRunner.wakeup(PooledTaskRunner.java:81)
    at org.apache.activemq.transport.failover.FailoverTransport.reconnect(FailoverTransport.java:757)
    at org.apache.activemq.transport.failover.FailoverTransport.start(FailoverTransport.java:344)
    at org.apache.activemq.transport.TransportFilter.start(TransportFilter.java:58)
    at org.apache.activemq.transport.TransportFilter.start(TransportFilter.java:58)

一開始,覺得是系統磁盤,或者內存佔滿致使。經過top命令查看系統信息。均屬於正常範圍。正在嘗試尋找其餘方案的同時。在SSH中輸入命令是。出現如下錯誤:tomcat

$ bash: fork: Resource temporarily unavailable

出現上述問題後:很是明顯的提示來資源不足致使。性能優化

經分析:是因爲當前系統使用的線程數大於ulimit中的max_user_processes的數量致使。bash

Linux ulimit 參數

  上面說到了,與系統(Linux)中的ulimit參數有關。ulimit 是用來限制系統資源的。
其中包括:微信

  1. max memory size (最大內存大小)。性能

  2. open files(打開文件數)。優化

  3. max user processes(最大用戶進程數)
    等等。spa

系統性能優化經常會優化此參數。.net

(有興趣的童鞋能夠自行了解更多)

ulimit 經常使用命令:

1. 顯示open files

$ ulimit -n
65535

其中 ulimit -n 顯示的結果爲: open files的數值。

2. 顯示當前用戶的最大進程數

$ ulimit -u
60000

其中ulimit -u 顯示的結果爲: max_user_processes額值。

2. 顯示ulimit 全部屬性

$ ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 127399
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 65535
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 10240
cpu time               (seconds, -t) unlimited
max user processes              (-u) 60000
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

其中:

  1. open files 表示打開文件的最大數。

  2. max user processes 當前用戶打開能打開的最大進程數。

(一) 修改 open files 數量

其中open files 屬性, 能夠在/etc/security/limits.conf文件中修改。在文件末尾添加。以下所示代碼:

*               soft    nofile          65535
*               hard    nofile          65535

其中:

  1. nofile 表示 open files

  2. nproc  對應的屬性爲: max_user_processes

  3. 其中 65535 爲演示數字。請按照環境的實際狀況進行調整。

(二) 修改 max_user_processes 數量

其中 max_user_processes屬性,能夠在/etc/security/limits.d/90-nproc.conf路徑下進行修改。
修改以下:

*          soft    nproc     60000
root       soft    nproc     unlimited

須要注意的是:

  1. max_user_processes中最大的值爲: 60000。
    若是設置超過60000,則默認爲最大值。例如: 設置 655535,則會爲60000。

  2. 執行上述步驟後。退出當前會話。從新鏈接便可生效!在修改以前鏈接的會話,須要從新鏈接,才能看到新的配置。

查看系統資源方法

1. 查看當前系統使用的進程數。      

  咱們可使用: ps aux|wc -l或者ps -ef|wc -l命令來查看當前正在使用的進程數。
以下所示:

$ ps aux|wc -l
309

有時經過ps aux|wc -l 命令查看獲得的數據少於max_user_processes 的值。
也出現:

$ bash: fork: Resource temporarily unavailable`

這是由於一個進程中能夠包含多個線程致使。

2. 查看指定進程數中的線程數。  

  當咱們知道了的進程ID(PID)後,
也能夠經過以下方法查看當前進程中有多少個線程:
命令:

$ cat /proc/<pid>/status

案例以下:

andy@andyqian:/java$ cat /proc/11723/status
Name:    java
State:    S (sleeping)
Tgid:    11723
Ngid:    0
Pid:    11723
PPid:    2434
TracerPid:    0
Uid:    1000    1000    1000    1000
Gid:    1000    1000    1000    1000
FDSize:    128
Groups:    4 24 27 30 46 108 124 1000 
Threads:    28
SigQ:    0/47456
Seccomp:    0
Cpus_allowed:    ff
Cpus_allowed_list:    0-7
Mems_allowed:    00000000,00000001
Mems_allowed_list:    0
voluntary_ctxt_switches:    88
nonvoluntary_ctxt_switches:    3

其中:

  1. Threads:28 就表示該進程中,一個有28個線程。

  2. 因爲篇幅緣由,以上刪除了部分信息。

3. 如何查看應用的進程   &nbsp;可能有童鞋不知道如何查看應用的進程數,這裏給個簡單的案例:
例如查看一個名命爲tomcat01的tomcat。咱們能夠經過以下命令查看:

ps -aux|grep tomcat01

以下所示:

andy@andyqian:/java$ ps -aux|grep tomcat01
andy     11723  0.5  1.0 6484560 127292 pts/1

其中: 11723 對應的就是tomcat01的進程ID。

這裏寫圖片描述

 掃碼關注,一塊兒進步

我的博客: http://www.andyqian.com

相關文章
相關標籤/搜索