Java JIT 编译器导致 OutOfMemoryError

标签 java jvm jit

我们最近启动的一个应用程序偶尔会崩溃,并显示有关“java.lang.OutOfMemoryError:为 Chunk::new 请求 8589934608 字节。交换空间不足?”的消息。

我在网上看了一圈,到处都是建议

  • 恢复到以前的 Java 版本
  • 摆弄内存设置
  • 使用客户端而不是服务器模式

恢复到以前的版本意味着新的 Java 有一个错误,但我还没有看到任何迹象。内 stub 本不是问题;服务器有 32GB 可用空间,Xmx 设置为 20,而 Xms 为 10。我看不到 JVM 用完了剩余的 12GB(减去机器上少数其他进程的数量)。由于应用程序和环境的性质,我们坚持使用服务器模式。

当我查看应用程序的内存和 CPU 使用情况时,我看到一整天的内存使用情况都在持续,但就在它消失之前突然 CPU 使用情况上升到 100%,内存使用情况从 X 到 X + 2GB,到 X + 4GB,到(有时)X + 8GB,到 JVM 死亡。似乎在 JIT 编译中可能存在重复调整数组大小的循环。

我现在已经看到上述 8GB 请求和 16GB 请求都发生了错误。在任何时候,发生这种情况时编译的方法都是相同的。它是一个简单的方法,没有嵌套循环,没有递归,并且在对象上使用方法直接返回静态成员字段或实例成员字段,计算量很小。

所以我有两个问题:

  1. 有人有什么建议吗?
  2. 我可以测试在测试环境中编译此特定方法是否存在问题,而不运行整个应用程序,直接调用 JIT 编译器吗?或者我应该启动应用程序并告诉它在调用次数少得多(比如 2)后编译方法,以强制它几乎立即编译方法,而不是在一天中的随机时间点编译方法?

@StephenC

JVM 是 1.6.0_20(以前是 1.6.0_0),在 Solaris 上运行。我知道是编译导致的问题有几个原因。

  1. ps 在它之前的几秒内显示一个 id 对应于编译器线程(来自 jstack)的 java 线程占用了 100% 的 CPU 时间
  2. jstack 显示问题出在 JavaThread "CompilerThread1"daemon [_thread_in_native, id=34, ...]

jstack中提到的方法总是同一个,而且是我们写的一个。如果您查看示例 jstack 输出,您就会明白我的意思,但出于显而易见的原因,我无法提供代码示例或文件名。我会说这是一个非常简单的方法。 Essential 少量空值检查,2 个用于执行相等性检查并可能分配值的循环,以及之后的一些简单方法调用。总共可能有 40 行代码。

这个问题在 2 周内发生了 2 次,尽管应用程序每天都在运行并且每天都会重新启动。此外,应用程序在任何时候都没有承受重负载。

最佳答案

您可以通过创建一个名为 .hotspot_compiler 的文件来排除特定方法被 JIT 处理并将其放入您的应用程序“工作目录”中。只需按以下格式在文件中添加一个条目:

exclude com/amir/SomeClass someMethod

编译器的控制台输出如下:

### Excluding compile:  com.amir.SomeClasst::someMethod

有关详细信息,请阅读 this .如果您不确定您的应用程序“工作目录”是什么,请使用

-XX:CompileCommandFile=/my/excludefile/location/.hotspot_compiler

在您的 Java 启动脚本或命令行中。

或者,如果您不确定它是 JIT 编译器的错误,并且想看看您是否可以在没有任何 JIT 的情况下重现该问题,请使用 -Xint 运行您的 Java 进程。 .

关于Java JIT 编译器导致 OutOfMemoryError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3455381/

相关文章:

java - 如何在 Visual Studio Code 上使用 web.xml 调试 spring mvc Web 应用程序?

java - 了解 hs_err_pid<n>.log 文件

java - 为什么Java虚拟机中没有GIL?为什么 Python 这么需要一个?

java - JVM 中的 JIT 编译器到底是什么?

java - 无法使用动态多态性访问方法[JAVA]

java - 在 Spring 3.1 mvc webservice 中设置响应的内容类型

python - PyPy 使用什么样的 JIT 编译器?

c# - 如何阻止 JIT 调试器介入崩溃的 wcf 服务?

java - 尽管显示值从方法 block 内部更改,但从 setter 设置私有(private)值 "balance"时出错

java - JIT 是这种行为的原因吗?