linux当前用户最大进程数上限 导致java OOM

  • 此文使用user表示Linux用户名

这种OOM是在启动线程时抛出。异常信息为unable to create new native thread 栈如下:

Exception in thread "main" 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 jdk.nashorn.internal.scripts.Script$1$\^shell\_.:program(<shell>:1)
	at jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:637)
	at jdk.nashorn.internal.runtime.ScriptFunction.invoke(ScriptFunction.java:494)
	at jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:393)
	at jdk.nashorn.internal.runtime.Context.eval(Context.java:738)
	at jdk.nashorn.internal.runtime.Context.eval(Context.java:673)
	at jdk.nashorn.tools.Shell.readEvalPrint(Shell.java:516)
	at jdk.nashorn.tools.Shell.run(Shell.java:168)
	at jdk.nashorn.tools.Shell.main(Shell.java:143)
	at jdk.nashorn.tools.Shell.main(Shell.java:119)

触发原理,在linux操作系统中,创建足够多线程,使当前用户在当前会话的子进程数量达到上限,再创建新线程便可触发。

查看和设置当前用户最大进程数

查看 ulimit -a 执行结果如下:

[user@localhost ~]$ 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) 190703
max locked memory       (kbytes, -l) 16384
max memory size         (kbytes, -m) unlimited
open files                      (-n) 40960
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 40960
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimite

-a 即查看所有限制项。单独查看当前用户最大进程数则是 ulimt -u

给当前用户设置的上限的方法,直接在命令行上执行 ulimit -u 10000 。当前用户在命令行的方式设置的值只能小于等于设置之前的值。设置完立即生效,只影响当前会话。

也可以通过root用户修改 /etc/security/limits.conf 中 用户 nproc 项 根据其中注释样例和已有配置即可。(在CentOs和eulerosv2r7.x86_64 会有一个单独的 /etc/security/limits.d/20-nproc.conf文件,用来配置nproc,非root用户默认4096。修改文件的设置方法会在用户重新登录后生效。)

触发方法
  • 查看最大进程数ulimit -u,统计已创建的子进程数, ps -efL | grep 当前用户名 | wc -l

    user@localhost:~> ulimit -u
    40960
    user@localhost:~> ps -efL | grep user| wc -l
    679
    
  • 根据上述查询结果设置一个较小容易达到的上限,当前已创建679,将上限降低更容易复现,此处将当前会话的最大进程数设置为1000 ulimit -u 1000

  • 可以使用java代码用循环创建线程即可,此处为了省去编译,采用jre目录下的jjs程序代替java。

    检查jre/bin目录有没有在path中,没有则 export PATH=$PATH:/${jrePath}/bin,后执行jjs

    会打印一个类似于python或者 nodejs交互式命令行

    user@localhost:~> jjs
    jjs> 
    

    往交互式命令行输入,以下两行js语句,用来循环创建线程。(触发前最好新开一个ssh会话)

    输入以下语句后回车。

    //直接将类名赋值给变量即可
    Th = java.lang.Thread
    //当前语句在jjs交互式命令行,需要单行输入
    for (var i = 0; i < 400; i++) { new Th(function () { print(Th.currentThread().getName());Th.sleep(500000); }).start(); }
    

    不出意外会抛出OOM,且当前会话的终端无法继续交互,待休眠结束,线程释放终端可以被释放。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值