如何解决 Java 错误 "pool-1-thread-xxxx" java.lang.OutOfMemory
How to solve Java error "pool-1-thread-xxxx" java.lang.OutOfMemory
我已经搜索了有关此问题的帖子,但没有看到与我类似的情况。
我的 java 控制台显示错误消息 "pool-1-thread-xxxx" java.lang.OutOfMemory
,如下图所示:
- 红线:CPU用法
- 绿线:内存使用情况
我已将 RAM 从 6G
增加到 10G
,并在启动程序之前在 *.bat
文件中设置 -Xms=8G -Xmx=8G -Xmn=3G
。我也一直在看性能监视器,但内存总是在 20% 左右。我不知道怎么会这样。有什么想法吗?
这是我的 run.bat
代码。
@echo off
javapro @java -Xoptimize -Xms8G -Xmx8G -Xmn3G -Xss1024k -XX:+UseConcMarkSweepGC -cp javaPro.exe;
cls
run.bat
- OS: windows 服务器 2012 R2
- Java版本:jre1.8.0_171
- 内存:10G
- CPU:2.5 GHz Intel Xeon(R)(超线程)
错误信息java.lang.OutOfMemoryError: unable to create new native thread
表示
the JVM is asking a new thread from the OS and the underlying OS
cannot allocate a new thread anymore.
参见OOM explanations and your specific case explained。
因此您不会在图表中看到高内存使用率,因为堆大小未接近其限制。
您必须检查您的应用程序代码并检查那里的线程池使用情况。没有源码就不好说了,不过可能有几点建议:
- 如果您使用
CachedThreadPoolExecutor
,则提交的任务可能不够快,因此您的应用无法处理所有提交的任务。
- 您可以使用具有最大 (
Integer.MAX_VALUE
) 容量的 FixedThreadPoolExecutor
,在这种情况下,您必须限制池容量及其队列大小。所以池吃掉了所有可用的线程并且 OOM
发生了。
通常,您应该始终控制线程池配置并确保它不会占用所有系统资源。
认为我找到了可能的原因/解决方法:
可以使用 ulimit -a
:
检查进程的软限制
$ cat /proc/22666/limits | grep processes
Max processes 1024 62265 processes
$ ulimit -a | grep processes
max user processes
为了更改这些值:
$ ulimit -Su 2000
$ ulimit -a | grep processes
max user processes (-u) 2000
$ cat /proc/22666/limits | grep processes
Max processes 2000
也可以调整默认配置:
使用以下内容修改 limits.conf 文件:
sudo nano /etc/security/limits.conf
或查看内部 /etc/security/limit.d/
.
为运行java
的用户添加以下内容。
limits.conf
#<domain> <type> <item> <value>
# adjust these values as needed:
someuser soft nofile 4096
someuser hard nofile 8192
然后使用以下内容修改 common-session
文件:
sudo nano /etc/pam.d/common-session
添加以下行:
普通会话
session required pam_limits.so
并重新启动 java。
- 另见 ThreadPoolExecutor ...
- 和 ThreadPoolExecutor Configuration.
对于 Windows 2012 服务器,这大致相同。
- 在 Tech Net 博客上查看 Pushing the Limits of Windows。
我已经搜索了有关此问题的帖子,但没有看到与我类似的情况。
我的 java 控制台显示错误消息 "pool-1-thread-xxxx" java.lang.OutOfMemory
,如下图所示:
- 红线:CPU用法
- 绿线:内存使用情况
我已将 RAM 从 6G
增加到 10G
,并在启动程序之前在 *.bat
文件中设置 -Xms=8G -Xmx=8G -Xmn=3G
。我也一直在看性能监视器,但内存总是在 20% 左右。我不知道怎么会这样。有什么想法吗?
这是我的 run.bat
代码。
@echo off
javapro @java -Xoptimize -Xms8G -Xmx8G -Xmn3G -Xss1024k -XX:+UseConcMarkSweepGC -cp javaPro.exe;
cls
run.bat
- OS: windows 服务器 2012 R2
- Java版本:jre1.8.0_171
- 内存:10G
- CPU:2.5 GHz Intel Xeon(R)(超线程)
错误信息java.lang.OutOfMemoryError: unable to create new native thread
表示
the JVM is asking a new thread from the OS and the underlying OS cannot allocate a new thread anymore.
参见OOM explanations and your specific case explained。
因此您不会在图表中看到高内存使用率,因为堆大小未接近其限制。
您必须检查您的应用程序代码并检查那里的线程池使用情况。没有源码就不好说了,不过可能有几点建议:
- 如果您使用
CachedThreadPoolExecutor
,则提交的任务可能不够快,因此您的应用无法处理所有提交的任务。 - 您可以使用具有最大 (
Integer.MAX_VALUE
) 容量的FixedThreadPoolExecutor
,在这种情况下,您必须限制池容量及其队列大小。所以池吃掉了所有可用的线程并且OOM
发生了。
通常,您应该始终控制线程池配置并确保它不会占用所有系统资源。
认为我找到了可能的原因/解决方法:
可以使用 ulimit -a
:
$ cat /proc/22666/limits | grep processes
Max processes 1024 62265 processes
$ ulimit -a | grep processes
max user processes
为了更改这些值:
$ ulimit -Su 2000
$ ulimit -a | grep processes
max user processes (-u) 2000
$ cat /proc/22666/limits | grep processes
Max processes 2000
也可以调整默认配置:
使用以下内容修改 limits.conf 文件:
sudo nano /etc/security/limits.conf
或查看内部/etc/security/limit.d/
.为运行
java
的用户添加以下内容。
limits.conf
#<domain> <type> <item> <value>
# adjust these values as needed:
someuser soft nofile 4096
someuser hard nofile 8192
然后使用以下内容修改 common-session
文件:
sudo nano /etc/pam.d/common-session
添加以下行:
普通会话
session required pam_limits.so
并重新启动 java。
- 另见 ThreadPoolExecutor ...
- 和 ThreadPoolExecutor Configuration.
对于 Windows 2012 服务器,这大致相同。
- 在 Tech Net 博客上查看 Pushing the Limits of Windows。