OutOfMemoryError即使有足够的可用内存

时间:2014-11-19 11:02:30

标签: java out-of-memory ulimit

我收到java.lang.OutOfMemoryError错误,即使我还有足够的可用内存。我采取的内存转储在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 { ... }块可解决问题。现在我想知道我达到了哪些限制(如果没有可用内存量)。服务器上的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

我达到了哪个限制?

1 个答案:

答案 0 :(得分:0)

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

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

通常,正如您的情况一样,获取此异常意味着您的应用程序未正确关闭其线程并保持系统进程。这就是关闭trasnport为你解决问题的原因。