【问题标题】:How to solve Java error "pool-1-thread-xxxx" java.lang.OutOfMemory如何解决 Java 错误“pool-1-thread-xxxx”java.lang.OutOfMemory
【发布时间】:2018-09-18 15:17:57
【问题描述】:

我已经搜索过有关此问题的帖子,但我没有看到像我这样的情况。

我的 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
  • 操作系统:windows server 2012 R2
  • Java 版本:jre1.8.0_171
  • 内存:10G
  • CPU:2.5 GHz Intel Xeon(R)(超线程)

【问题讨论】:

  • 能否给出你的线程池的代码?
  • 很难说没有实际代码。您在pool-1 上的线程号是1395,因此您至少有1395 个线程在运行。消息OOM: unable to create native thread 表示没有可用的系统资源来分配新线程。请发布一些代码,也许您在那里使用CachedThreadPoolExecutor,但任务不够短,所以系统炸毁了。查看更多关于OOM explanation here
  • 您似乎在应用程序中创建了许多线程。您应该向我们展示您尝试执行的主要代码,您可能在那里有问题,并且与您的内存配置无关。是否会在您尝试对应用程序执行的操作中创建这么多新线程?
  • 很遗憾我没有源代码。是否有可能增加线程池限制?

标签: java out-of-memory threadpool


【解决方案1】:

错误信息java.lang.OutOfMemoryError: unable to create new native thread表示

JVM 正在向操作系统和底层操作系统请求一个新线程 不能再分配新线程了。

请参阅 OOM explanationsyour specific case explained

因此您不会在图表中看到高内存使用率,因为堆大小未接近其限制。

您必须检查您的应用程序代码并检查那里的线程池使用情况。没有源代码很难说什么,但可能有一些建议:

  1. 如果您使用CachedThreadPoolExecutor,那么提交的任务可能不够快,导致您的应用无法处理所有提交的任务。
  2. 您可以使用具有最大 (Integer.MAX_VALUE) 容量的 FixedThreadPoolExecutor,在这种情况下,您必须限制池容量及其队列大小。所以池吃掉了所有可用的线程,OOM 发生了。

通常,您应该始终控制您的线程池配置,并确保它不会占用所有系统资源。

【讨论】:

  • 是的,我想这就是原因。很好的答案,谢谢。
  • @david0116 command ulimit -a 仅显示 Linux 服务器上的软限制,而这甚至不是 Linux 服务器的可行解决方案,即使第二个链接大胆地假装它是“解决方案”(除非调整这些值,否则它不是)。
  • @MartinZeitler ulimit -a 是操作系统级别的设置,但错误发生在 Java 进程中,可能应该在同一范围内修复。您的回答可能会解决问题(我赞成),但不会消除根本原因。 Java 线程池应在 JVM 中正确配置。我只是试图在这里解释潜在的问题。作者现在可以检查源代码并修复实际原因。
  • @VladimirVagaytsev Java 不能保留比操作系统提供的更多的内存/线程 - 这就是最大利用率低于理论上分配给 JVM 的原因。 Java管理的线程池永远不会超过操作系统的限制,就像操作系统永远不会超过硬件的限制一样;不完全一样KVM
  • @MartinZeitler 确实如此,但这并不意味着您不应该在 JVM/Java 级别上设置任何线程池或内存限制。每次运行 Java 应用程序时,都必须注意堆大小和线程池容量。如果您的要求超出了操作系统的能力,那么您应该调整操作系统参数。所以这两个答案的结合给出了更好的解释:)
【解决方案2】:

认为我找到了可能的原因/解决方法:

可以使用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 

也可以调整默认配置:

  1. 使用以下内容修改limits.conf 文件:

  2. sudo nano /etc/security/limits.conf 或查看内部/etc/security/limit.d/

  3. 为运行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。

对于 Windows 2012 Server,情况大致相同。

【讨论】:

  • windows server 2012怎么样? limits.conf 文件位置在哪里?
  • @david0116 这适用于 Linux 服务器,而 Windows 2012 Server ™ 应该对每个用户的限制具有大致相同的设置(相同的 Java 错误消息提示)。查看服务器管理控制台:docs.microsoft.com/en-us/windows-server/administration/… 如果不存在,则可能存在具有这些限制的注册表项。
  • @david0116 这可能不是错误,而是系统安全/稳定性功能。
  • 其实我觉得这个答案真的很接近被接受了。由于我的错误消息显示“pool-1-thread-1395”,我认为 1395 个线程不是正常的线程限制量。由于某些原因,例如您的答案,它受到限制。如果您不介意,我可以发布一个关于增加 Windows 的 java 线程限制的新问题吗?我还是找不到怎么做。
猜你喜欢
  • 2023-02-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多