java - OutOfMemoryError 即使有足够的可用内存

标签 java out-of-memory ulimit

我收到 java.lang.OutOfMemoryError 错误,即使我还有足够的空闲 RAM。我进行的内存转储在 200MB 到 1GB 之间,而我的服务器有 24GB 的 RAM。我设置了 -Xmx12288m -Xms12288m

此外,当我尝试登录服务器时,我经常得到

-bash: fork: retry: Resource temporarily unavailable
-bash: fork: retry: Resource temporarily unavailable
-bash: fork: retry: Resource temporarily unavailable
-bash: fork: retry: Resource temporarily unavailable
-bash: fork: Resource temporarily unavailable

我将其缩小为以下代码片段:

import org.snmp4j.Snmp;
import org.snmp4j.transport.DefaultUdpTransportMapping;

    long n = 0;
    while (true) {
        DefaultUdpTransportMapping transport = null;
        try {
            transport = new DefaultUdpTransportMapping();
            transport.listen();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
//      } finally {             // (*) I forgot this
//          transport.close();  // (*) I forgot this
        }

        n++;
        double freeMemMB = Runtime.getRuntime().freeMemory() / 1024 / 1024;
        System.out.println("Created " + n
                + " DefaultUdpTransportMappings. Free Mem (mb): "
                + freeMemMB);
    }

输出(在我的开发机器上,使用 mvn exec:java):

Created 2026 DefaultUdpTransportMappings. Free Mem (mb): 299.0
Created 2027 DefaultUdpTransportMappings. Free Mem (mb): 299.0
[WARNING] 
java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.codehaus.mojo.exec.ExecJavaMojo$1.run(ExecJavaMojo.java:293)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.OutOfMemoryError: unable to create new native thread
    at java.lang.Thread.start0(Native Method)
    at java.lang.Thread.start(Thread.java:714)
    at org.snmp4j.util.DefaultThreadFactory$WorkerThread.run(DefaultThreadFactory.java:91)
    at org.snmp4j.transport.DefaultUdpTransportMapping.listen(DefaultUdpTransportMapping.java:168)
    at App.main(App.java:19)
    ... 6 more

我发现我收到错误是因为我没有关闭 DefaultUdpTransportMapping。启用 finally { ... } block 可以解决问题。现在我想知道我达到了哪些限制(如果不是可用内存量)。服务器上的 ulimits 是:

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

在我的开发者 Mac 上:

-t: cpu time (seconds)              unlimited
-f: file size (blocks)              unlimited
-d: data seg size (kbytes)          unlimited
-s: stack size (kbytes)             8192
-c: core file size (blocks)         0
-v: address space (kbytes)          unlimited
-l: locked-in-memory size (kbytes)  unlimited
-u: processes                       709
-n: file descriptors                2560

我达到了哪个限制?

最佳答案

java.lang.OutOfMemoryError: unable to create new native thread 是一个令人困惑的消息,因为它与堆内存耗尽并没有真正的关系。因此,堆大小设置(Xmx 和 Xms)对这种情况没有影响。 当无法为您的应用程序创建新的操作进程时抛出异常,这可能是因为达到了进程/打开文件句柄的最大数量,或者系统上没有剩余内存来创建新线程。

关于 ulimit 设置,它可以是文件描述符的数量、堆栈大小或进程的数量。堆栈大小是每个线程数,线程数乘以堆栈大小将是已用内存量。

通常,根据您的情况,出现此异常意味着您的应用程序未正确关闭其线程并保留系统进程。这就是关闭传输为您解决问题的原因。

关于java - OutOfMemoryError 即使有足够的可用内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27015226/

相关文章:

matlab - 在matlab中将两个大矩阵相乘会产生内存不足错误

windows - 限制 Maya 在 Windows 上可以打开的文件数量

linux - 如何在 Ubuntu 中增加 Neo4j 的最大文件打开限制(ulimit)?

amazon-web-services - 在 AWS ECS : HardLimit cannot be empty 中设置 ulimit

java - MVC 和 JavaServer Faces

java - 如何解决java.lang.NoSuchMethodError : org. hibernate.integrator.internal.IntegratorServiceImpl

java - 二进制转十进制 - java

java - 为什么 Java 允许捕获应用程序不应该处理的错误类型?

java - Java 中的功能测试

java - Java中字符串的不可变性会导致内存不足吗