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

Java:无法创建新的本机线程,java,out-of-memory,Java,Out Of Memory,我有一个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) 托

我有一个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配置/OS资源中


如何防止发生此错误?

您是否进行过内存跟踪?启动jconsole,在24小时内观察或记录内存消耗。如果它(平均)上升而没有下降,那么您的内存不足,可能没有足够的内存来存储新线程的详细信息。

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


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


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

看起来像线程泄漏。线程被创建,但随后被卡在某个地方。定期转储线程,以查看分配的线程数是否在增长。在转储中查找任何休眠/挂起的线程

kill -QUIT jvm_pid

linux的问题是要处理多少打开的文件 给出如下 乌利米特-n 65536
(您可以提供的任何数量)

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

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

例如,当您的用户出现这种情况时,“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-不同发行版的结果可能略有不同。

这个答案是给所有通过systemd运行java的人的。 (例如自创的tomcat服务)

我通过Tomcat在服务器上运行java应用程序。 为了方便起见,我还在systemd中创建了一个服务单元,因此它在服务器启动时启动,我还可以通过systemd(或
服务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

这也可能是应用程序创建太多线程的一个问题——正如本文所提到的,更多线程==更多本机空间内存使用,这可以通过调优来解决。。这假定应用程序所需的线程数是合法的。但是,如果应用程序产生了线程并且从未杀死它们(线程泄漏),那么再多的调优也无法修复它。也可能是操作系统对每个进程的线程数有限制。java代码本身有没有简单的方法来获取与我的进程相关联的线程数?由于这是一家网络托管公司JVM,我几乎无法访问JVM级别的工具。不过我可以插入我的代码。。(这就是我获取JVM内存信息所做的)。这是不可能的,但托管公司有一个支持团队,如果你教他们怎么做,他们可以为你转储线程。我不相信我会得到“无法创建新的本机线程”这是OOM消息的一部分,如果这是一个标准内存泄漏。请理解,我使用的是最一般意义上的术语,因为在java中无法直接分配内存,然后会像在C中一样失去对它的跟踪。您如何清理启动的这些线程?谢谢,使用arduino和Xms100m解决了这个错误!我在Fedora 20上也遇到了月食Luna的问题。我已经读了很多关于不同内存选项的书,但仍然无法解决这个问题。这让我发疯。最后我意识到,默认情况下,常规用户可以在Fedora上拥有的进程数量非常有限。limits.d/90-nproc.conf的内容:*软nproc 1000将其提高到5000修复了我的“无法创建新的本机线程”问题。