Java:无法创建新的本机线程

时间:2011-03-09 22:31:32

标签: java out-of-memory

我有一个由Web托管公司托管的Java应用程序。每隔几天我的应用就会失败:

[2011-03-09 15:52:14,501] ERROR http-12021-9 
java.lang.OutOfMemoryError: unable to create new native thread
    at java.lang.Thread.start0(Native Method)
    at java.lang.Thread.start(Thread.java:597)

托管公司表示这意味着我的应用程序正在泄漏内存,但我现有的工具显示可用内存仍然可用。由于错误总是创建一个新的本机线程,我认为问题出在JVM配置/操作系统资源中。

如何防止此错误发生?

7 个答案:

答案 0 :(得分:7)

最有可能的问题是JVM在Web服务器端。有关详细信息,请查看以下链接

http://blog.egilh.com/2006/06/2811aspx.html

答案 1 :(得分:5)

一种可能性是您已达到打开文件数量的用户限制。

我相信每个进程/线程都会使用一个或多个文件描述符。

例如,当您的用户发生这种情况时,“no”shell命令将起作用,因为shell命令分叉执行的进程(您会看到诸如“-bash:fork:retry:Resource temporary unavailable”之类的错误)

我遇到了这个问题,发现只有当前用户无法产生过程...其他用户不受影响。

要解决,请启动你的ulimit -n(最大文件打开)设置......详细信息如下。

您可以使用以下命令查看用户限制:

ulimit -a

使用以下内容提高最大文件限制:

ulimit -n 65536 

这就是我现在所拥有的:

$ 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) 256797
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 75000
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) 100000
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

要查看系统的所有明确限制:

cat /etc/security/limits.conf

请注意:我使用的是Oracle Linux 6.3 - 发行版之间的结果可能略有不同。

答案 2 :(得分:2)

启动进程时,JVM的堆大小有限(默认为128MB)。该服务器可能拥有更多内存,但您的JVM却没有 - 您全部使用它。

您可以使用-Xms-Xmx命令行参数进行更改,但我建议先查找内存泄漏:)

答案 3 :(得分:1)

你有没有进行内存跟踪?启动jconsole并在24小时内观察或记录您的内存消耗。如果它(平均)上升而没有回落,那么你的内存不足,可能没有足够的内存来存储新线程的细节。

答案 4 :(得分:1)

linux的问题是处理no.of打开的文件 给出如下 ulimit -n 65536 (您可以提供的任何数字)

答案 5 :(得分:0)

看起来线程泄漏。线程已创建但随后卡在某处。定期转储线程以查看分配的线程数是否在增长。寻找转储中的任何睡眠/悬挂线程。

kill -QUIT jvm_pid

答案 6 :(得分:0)

此答案适用于所有通过systemd运行Java的人。 (例如,自行创建的tomcat服务)

我正在通过Tomcat在服务器上运行Java应用程序。 为了方便起见,我还在systemd中创建了一个服务单元,因此它会在服务器启动时启动,我也可以通过systemd(或service tomcat restart)对其进行控制。

但是systemd单位及其最大允许任务(线程)有一些默认值。对我来说,这是195个任务。 一旦我用TasksMax=1024更改了服务单元中的值,并用systemctl daemon-reload重新加载了该值,一切就按预期工作了。

例如/etc/systemd/system/tomcat.service

中的服务单元文件
[Unit]
Description=Tomcat9
After=network.target

[Service]
Type=forking
User=tomcat9
Group=tomcat9

TasksMax=1048

Environment=CATALINA_PID=/opt/tomcat/tomcat9.pid
Environment=JAVA_HOME=/usr/lib/jvm/default-java
Environment=CATALINA_HOME=/opt/tomcat
Environment=CATALINA_BASE=/opt/tomcat
Environment="CATALINA_OPTS=-Xms2048m -Xmx28384m"
Environment="JAVA_OPTS=-Dfile.encoding=UTF-8 -Dnet.sf.ehcache.skipUpdateCheck=true -XX:+UseConcMarkSweepGC -XX:+CMSClassUnloadingEnabled -XX:+UseParNewGC"

ExecStart=/opt/tomcat/bin/startup.sh
ExecStop=/opt/tomcat/bin/shutdown.sh

[Install]
WantedBy=multi-user.target