原文:https://my.oschina.net/u/1462914/blog/1630086

引言

熟悉Java的童鞋,应该对OOM比较熟悉。该类问题,一般都比较棘手。因为造成此类问题的原因有很多。今天就分享一个非常有意思的案例。(说实话。这个问题,我也是前两天才遇到的。花了不少时间来分析。觉得非常有意思,记录在此。大神勿喷!)

问题场景

重启应用时,调试到给MQ发消息时。有如下错误:

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中输入命令是。出现以下错误:

$ bash: fork: Resource temporarily unavailable

出现上述问题后:非常明显的提示来资源不足导致。

经分析:是由于当前系统使用的线程数大于ulimit中的max_user_processes的数量导致。

Linux ulimit 参数

上面说到了,与系统(Linux)中的ulimit参数有关。ulimit 是用来限制系统资源的。
其中包括:

  1. max memory size (最大内存大小)。

  2. open files(打开文件数)。

  3. max user processes(最大用户进程数)
    等等。

系统性能优化常常会优化此参数。

(有兴趣的童鞋可以自行了解更多)

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。

记一个有趣的Java OOM!的更多相关文章

  1. salesforce零基础学习(一百一十五)记一个有趣的bug

    本篇参考:https://help.salesforce.com/s/articleView?language=en_US&type=1&id=000319486 page layou ...

  2. 【bug】记一个有趣的“bug”

    产品经理在使用我们用户功能的是,需要查询一个用户,知道这个用户的id,我说支持模糊查询的. 他输入"余XX",点击查询,怎么都查不出这个用户. 我到用户表里确认,确实有这个ID的用 ...

  3. 记一个社交APP的开发过程——基础架构选型(转自一位大哥)

    记一个社交APP的开发过程——基础架构选型 目录[-] 基本产品形态 技术选型 最近两周在忙于开发一个社交App,因为之前做过一点儿社交方面的东西,就被拉去做API后端了,一个人头一次完整的去搭这么一 ...

  4. dubbo debug过程中一个有趣的问题

    最近在debug dubbo代码过程中遇到的很有趣的问题 我们都知道dubbo ReferenceBean是消费者的spring bean包装,为了查一个consumer端的问题,在Reference ...

  5. Java OOM 常见情况

    Java OOM 常见情况 原文:https://blog.csdn.net/qq_42447950/article/details/81435080 1)什么是OOM?  OOM,全称“Out Of ...

  6. Java OOM学习

    转载自原文: 什么是java OOM?如何分析及解决oom问题? 什么是OOM? OOM,全称"Out Of Memory",翻译成中文就是"内存用完了",表现 ...

  7. 举一个有趣的例子,让你轻松搞懂JVM内存管理

    目录 前言 例子 源码 输出 图解 深入分析 学以致用 写在最后 前言 在JAVA虚拟机内存管理中,堆.栈.方法区.常量池等概念经常被提到,对理论知识的理解也常常停留在字面意思上,比如说堆内存中存放对 ...

  8. 怒肝俩月,新鲜出炉史上最有趣的Java小白手册,第一版,每个 Java 初学者都应该收藏

    这么说吧,在我眼里,Java 就是最流行的编程语言,没有之一(PHP 往一边站).不仅岗位多,容易找到工作,关键是薪资水平也到位,不学 Java 亏得慌,对吧? 那可能零基础学编程的小伙伴就会头疼了, ...

  9. Linux环境下部署完JDK后运行一个简单的Java程序

    前言 前一篇文章详细讲解了如何在Windows环境下安装虚拟机+Linux系统,并且成功部署了JDK. 不过部署完JDK之后,我们判断部署是否成功的依据是看"java -version&qu ...

随机推荐

  1. JMeter 中 HTTP Cookie 管理器的使用

    根据 web 应用的复杂度你可以选择创建两种类型的 JMeter 测试计划:面向点击数的或面向场景的. 创建一个面向点击数的测试计划你需要有中值统计.这些统计要包含你的应用每秒应该处理多少个独立请求的 ...

  2. C语言 ,两个字符串参数,判断是否包含另一个字符串,返回所在位置

    char * cyp(char *s1,char *s2) { char *p = NULL; char *q = NULL; char *q1 = NULL; while(*s1!='\0') { ...

  3. hdu 1243(LCS变形)

    反恐训练营 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submi ...

  4. Integer to Roman——相当于查表法

    Given an integer, convert it to a roman numeral. Input is guaranteed to be within the range from 1 t ...

  5. opencv python基本操作

    Python usage crop frame: croppedframe = frame[ymin:ymax, xmin:xmax] resize frame: reszframe = cv2.re ...

  6. python 用abc模块构建抽象基类Abstract Base Classes

    见代码: #!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2018/08/01 16:58 from abc import ABCMet ...

  7. CentOS安装指定版本GCC

    系统是CentOS 7, 自带的gcc是4.8.4 准备工作: 下载GCC源码包 gcc-5.5.0.tar.gz,地址(清华大学开源软件镜像站ipv6)(备选地址->gnu->gcc) ...

  8. 【剑指offer】面试题 11. 旋转数组的最小数字

    面试题 11. 旋转数组的最小数字 题目描述 题目:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转. 输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素. 例如数组{3,4, ...

  9. (8)go 字符串

    内建函数在 包中 1. len(str) 计算长度,中文占3个字符 2.字符串遍历,同时处理中文 package main import ( "fmt" ) func main() ...

  10. SGU167 I-country

    嗯以前在某个DP专题了发过这道题,但是当时没码代码,现在重发一篇题解 思考阶段如何划分:由已经处理的行数向下扩展,但是仅有行数我们无法描述状态空间那我们再加入已经选过的格子数,这样我们似乎可以确定我们 ...