Linux Java 内存错误:无法创建新的本机线程

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8203156/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 02:23:41  来源:igfitidea点击:

Java Memory error: unable to create new native thread

javalinuxmultithreadingmemorydebian

提问by Joel

I get this error on my UNIX server, when running my java server:

运行我的 Java 服务器时,我在 UNIX 服务器上收到此错误:

Exception in thread "Thread-0" java.lang.OutOfMemoryError: unable to create new native thread
at java.lang.Thread.start0(Native Method)
at java.lang.Thread.start(Thread.java:640)
at [... where ever I launch a new Thread ...]

It happens everytime I have about 600 threads running.

每次运行大约 600 个线程时都会发生这种情况。

I have set up this variable on the server:

我已经在服务器上设置了这个变量:

$> ulimit -s 128

What looks strange to me is the result of this command, which I ran when the bug occured the last time:

令我感到奇怪的是此命令的结果,我在上次出现错误时运行了该命令:

$> free -m
              total       used       free     shared    buffers     cached
Mem:          2048        338       1709          0          0          0
-/+ buffers/cache:        338       1709
Swap:            0          0          0

I launch my java server like this:

我像这样启动我的java服务器:

$> /usr/bin/java -server -Xss128k -Xmx500m -jar /path/to/myJar.jar

My debian version:

我的 debian 版本:

$> cat /etc/debian_version
5.0.8

My java version:

我的Java版本:

$> java -version
java version "1.6.0_26"
Java(TM) SE Runtime Environment (build 1.6.0_26-b03)
Java HotSpot(TM) 64-Bit Server VM (build 20.1-b02, mixed mode)

My question: I have read on Internet that my program should handle something like 5000 threads or so. So what is going on, and how to fix please ?

我的问题:我在互联网上读到我的程序应该处理大约 5000 个线程。那么这是怎么回事,请问如何解决?



Edit: this is the output of ulimit -awhen I open a shell:

编辑:这是ulimit -a我打开外壳时的输出:

core file size          (blocks, -c) unlimited
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 794624
max locked memory       (kbytes, -l) 32
max memory size         (kbytes, -m) unlimited
open files                      (-n) 100000
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) 794624
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

I run the script as a daemon from init.d, and this is what i run:

我将脚本作为 init.d 的守护进程运行,这就是我运行的内容:

DAEMON=/usr/bin/java
DAEMON_ARGS="-server -Xss128k -Xmx1024m -jar /path/to/myJar.jar"
ulimit -s 128 && ulimit -n 10240 && start-stop-daemon -b --start --quiet --chuid $USER -m -p $PIDFILE --exec $DAEMON -- $DAEMON_ARGS \
    || return 2


Edit2: I have come across this stack overflow question with a java test for threads: how-many-threads-can-a-java-vm-support

Edit2:我在线程的 Java 测试中遇到了这个堆栈溢出问题:how-many-threads-can-a-java-vm-support

    public class DieLikeADog { 
        private static Object s = new Object(); 
        private static int count = 0; 
        public static void main(String[] argv){ 
            for(;;){ 
                new Thread(new Runnable(){ 
                        public void run(){ 
                            synchronized(s){ 
                                count += 1; 
                                System.err.println("New thread #"+count); 
                            } 
                            for(;;){ 
                                try { 
                                    Thread.sleep(100); 
                                } catch (Exception e){ 
                                    System.err.println(e); 
                                } 
                            } 
                        } 
                    }).start(); 
            } 
        } 
    } 

On my server, the program crashes after 613 threads. Now i'm certain this is not normal, and only related to my server configuration. Can anyone help please ?

在我的服务器上,程序在 613 个线程后崩溃。现在我确定这不正常,只与我的服务器配置有关。有人可以帮忙吗?



Edit 3: I have come across this article, and many others, explaining that linux can't create 1000 threads, but you guys are telling me that you can do it on your systems. I don't understand.

编辑 3:我遇到了这篇文章,还有很多其他文章,解释说linux 不能创建 1000 个线程,但是你们告诉我,你可以在你的系统上做到这一点。我不明白。

I have also ran this script on my server: threads_limits.cand the limit is around 620 threads.

我也在我的服务器上运行了这个脚本:threads_limits.c并且限制是大约 620 个线程。

My website is now offline and this is the worst thing that could have happened to my project. I don't know how to recompile glibc and this stuff. It's too much work imo.

我的网站现在离线,这是我的项目可能发生的最糟糕的事情。我不知道如何重新编译 glibc 和这些东西。海事组织的工作太多了。

I guess I should switch to windows server. Because none of the settings proposed on this page did make any change: The limit on my system is between 600 and 620 threads, no matter the program involved.

我想我应该切换到 Windows 服务器。因为此页面上建议的设置均未进行任何更改:无论涉及哪个程序,我的系统的限制都在 600 到 620 个线程之间。

采纳答案by Joel

Just got the following information: This is a limitation imposed by my host provider. This has nothing to do with programming, or linux.

刚刚得到以下信息:这是我的主机提供商强加的限制。这与编程或linux无关。

回答by Sid Malani

Its going out of memory.

它的内存不足。

Also need to change ulimit. If your OS does not give your app enough memory -Xmx i suppose will not make any difference.

还需要改变ulimit。如果你的操作系统没有给你的应用足够的内存 -Xmx 我想不会有任何区别。

I guess the -Xmx500m is having no effect.

我猜 -Xmx500m 没有效果。

Try

尝试

ulimit -m 512m with -Xmx512m

ulimit -m 512m 和 -Xmx512m

回答by esaj

The underlying operating system (Debian Linux in this case) does not allow the process to create any more threads. See here how to raise the maximum amount: Maximum number of threads per process in Linux?

底层操作系统(在本例中为 Debian Linux)不允许该进程创建更多线程。请参阅此处如何提高最大数量:Linux 中每个进程的最大线程数?

I have read on Internet that my program should handle something like 5000 threads or so.

我在互联网上读到我的程序应该处理大约 5000 个线程。

This depends on the limits set to the OS, amount of running processes etc. With correct settings you can easily reach that many threads. I'm running Ubuntu on my own computer, and I can create around 32000 threads before hitting the limit on a single Java program with all my "normal stuff" running on the background (this was done with a test program that just created threads that went to sleep immediately in an infinite loop). Naturally, that high amount of threads actually doing something would probably screech consumer hardware to a halt pretty fast.

这取决于对操作系统设置的限制、正在运行的进程数量等。通过正确的设置,您可以轻松访问那么多线程。我在自己的计算机上运行 Ubuntu,在达到单个 Java 程序的限制之前,我可以创建大约 32000 个线程,而我的所有“正常东西”都在后台运行(这是通过一个刚刚创建线程的测试程序完成的)在无限循环中立即进入睡眠状态)。自然地,大量线程实际上在做某事可能会非常快地使消费者硬件停止运行。

回答by souser

Can you try the same command with a smaller stack size "-Xss64k" and pass on the results ?

您可以尝试使用较小堆栈大小“-Xss64k”的相同命令并传递结果吗?

回答by Adam Zalcman

Your JVM fails to allocate stack or some other per-thread memory. Lowering the stack size with -Xsswill help increase the number of threads you can create before OOM occurs (but JVM will not let you set arbitrarily small stack size).

您的 JVM 无法分配堆栈或其他一些每线程内存。降低堆栈大小-Xss将有助于在 OOM 发生之前增加您可以创建的线程数(但 JVM 不会让您设置任意小的堆栈大小)。

You can confirm this is the problem by seeing how the number of threads created change as you tweak -Xssor by running straceon your JVM (you'll almost certainly see an mmap()returning ENOMEMright before an exception is thrown).

您可以通过查看创建的线程数在您调整时如何变化-Xss或通过在 JVM 上运行strace来确认这是问题所在(您几乎肯定会在抛出异常之前看到mmap()返回ENOMEM)。

Check also your ulimiton virtual size, i.e. ulimit -v. Increasing this limit should let you create more threads with the same stack size. Note that resident set size limit (ulimit -m) is ineffective in current Linux kernel.

还要检查您ulimit的虚拟大小,即ulimit -v. 增加此限制应该可以让您创建更多具有相同堆栈大小的线程。注意 resident set size limit( ulimit -m)在当前的 Linux 内核中无效的

Also, lowering -Xmxcan help by leaving more memory for thread stacks.

此外,降低-Xmx可以通过为线程堆栈留出更多内存来提供帮助。

回答by KarlP

I am starting to suspect that "Native Posix Thread Library" is missing.

我开始怀疑缺少“本机 Posix 线程库”。

>getconf GNU_LIBPTHREAD_VERSION

Should output something like:

应该输出类似:

NPTL 2.13

If not, the Debian installation is messed up. I am not sure how to fix that, but installing Ubuntu Server seems like a good move...

如果没有,Debian 安装就搞砸了。我不知道如何解决这个问题,但安装 Ubuntu Server 似乎是一个不错的举动......

for ulimit -n 100000; (open fd:s) the following program should be able to handle 32.000 threads or so.

对于 ulimit -n 100000;(打开 fd:s)以下程序应该能够处理 32.000 个左右的线程。

Try it:

尝试一下:

package test;

import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.concurrent.Semaphore;

public class Test {

    final static Semaphore ss = new Semaphore(0);


    static class TT implements Runnable {

        @Override
        public void run() {
            try {
                Socket t = new Socket("localhost", 47111);
                InputStream is = t.getInputStream();
                for (;;) {
                    is.read();
                }

            } catch (Throwable t) {
                System.err.println(Thread.currentThread().getName() + " : abort");
                t.printStackTrace();
                System.exit(2);
            }

        }
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        try {

            Thread t = new Thread() {
                public void run() {
                    try {
                        ArrayList<Socket> sockets = new ArrayList<Socket>(50000);
                        ServerSocket s = new ServerSocket(47111,1500);
                        ss.release();

                        for (;;) {
                            Socket t = s.accept();
                            sockets.add(t);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                        System.exit(1);

                    }
                }
            };


            t.start();
            ss.acquire();


            for (int i = 0; i < 30000; i++) {

                Thread tt = new Thread(new TT(), "T" + i);
                tt.setDaemon(true);
                tt.start();
                System.out.println(tt.getName());
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    return;
                }
            }

            for (;;) {
                System.out.println();
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    return;
                }
            }

        } catch (Throwable t) {
            t.printStackTrace();
        }
    }
}