在 Redhat CentOS 6.4 上,只有几个进程在运行,使用大约 3GB RAM(系统有 12GB 可用)。其中一个进程是 WSO2ESB 服务器(java),我们使用以下参数启动它:
-Xms2048m -Xmx3072m
过了一会儿,我们得到了一个 OutOfMemory 异常,但是java 进程(WSO2ESB)甚至没有使用其 3GB。在 jconsole 中,您还可以看到这些参数设置正确(此时 Linux 服务器有大约 9GB 的可用 RAM)
Linux 没有给我们配置 3 GByte RAM 吗?
在完全相同的 Windows 安装上 - java 进程可以毫无问题地使用其 3GB Ram。
jconsole 的屏幕截图显示堆内存使用量仅在 0.3 到 1.0 GB 之间。在发生 OutOfMemory 异常时,堆内存为 0.5GB,但该进程可以使用 3GB,但它没有...
编辑:添加了 java 进程的日志:
java.lang.OutOfMemoryError: unable to create new native thread
EDIT2:添加了 free -m 输出:
答案1
我解决了这个问题。wso2esb 使用了超过 1000 个线程。但在 Linux 上,用户可以使用的默认线程数量设置为 1024。我不得不提高用户的限制,现在一切都正常了。
为此:打开 /etc/security/limits.conf 并为您的用户添加以下两行:
myuser soft nproc 8192
myuser hard nproc 8192
答案2
Java的堆空间有多个代,新生代、老生代。
如果您将 Xmx 设置得非常高,则它用于堆,即使您不使用整个堆,也可能会耗尽内存。如果您耗尽了 PermGen 空间,通常会发生这种情况。
永久代堆用于存储字符串池和 JVM 所需的与类、方法和其他 Java 原语相关的各种元数据。永久代空间通常为 64MB,因此如果您有很多类或巨大的字符串,您可能会用完它。
尝试通过添加以下内容来增加 permgen 的大小:
-XX:MaxPermSize=256m
到您的 java 启动选项。
答案3
堆的数据段大小是多少-Xms2048m -Xmx3072m
。
您的数据段大小应与您的最大堆大小相对应(在本例中为 3072m)。因此,您的数据段大小应至少设置为3221225472
(以字节为单位 3*1024*1024*1024 = 3GB)