Java JIT编译器导致OutOfMemoryError [英] Java JIT Compiler causing OutOfMemoryError

查看:95
本文介绍了Java JIT编译器导致OutOfMemoryError的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

An application that we have recently started sporadically crashing with a message about "java.lang.OutOfMemoryError: requested 8589934608 bytes for Chunk::new. Out of swap space?".

我在网上四处张望,到处都有建议仅限于

I've looked around on the net, and everywhere suggestions are limited to

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

恢复到以前的版本意味着新的Java有一个错误,但是我没有看到任何指示.内存根本不是问题.服务器有32GB可用空间,而Xmx设置为10时Xmx设置为20.我看不到JVM用完了剩余的12GB(减去分配给计算机上少数其他进程的数量).而且由于应用程序和环境的性质,我们陷入了服务器模式.

Reverting to a previous version implies that the new Java has a bug, but I haven't seen any indication of that. The memory isn't an issue at all; the server has 32GB available, and Xmx is set to 20 while Xms is 10. I can't see the the JVM running out of the remaining 12GB (less the amount given to the handful of other processes on the machine). And we're stuck with server mode due to the nature of the application and environment.

当我查看应用程序的内存和CPU使用率时,我发现整天的内存使用率是恒定的,但是在它死之前突然突然CPU使用率上升到100%,并且内存使用率从X变为X + 2GB,至X + 4GB,至(有时)X + 8GB,导致JVM死亡.似乎在JIT编译中可能存在重复数组调整大小的循环.

When I look at the memory and CPU usage for the application, I see constant memory usage for the whole day, but then suddenly right before it dies CPU usage goes up to 100% and the memory usage goes from X, to X + 2GB, to X + 4GB, to (sometimes) X + 8GB, to JVM death. It would appear that there is maybe cycle of repeated array resizing going on in the JIT compilation.

我现在已经看到上述8GB请求和16GB请求都发生了错误.在所有情况下,发生这种情况时正在编译的方法都是相同的.这是一种简单的方法,它具有非嵌套循环,没有递归,并且在对象上使用的方法只需很少的计算即可直接返回静态成员字段或实例成员字段.

I've now seen the error occur with the above 8GB request and also 16GB requests. All times, the method being compiled when this happens is the same. It is a simple method that has non-nested loops, no recursion, and uses methods on objects that return static member fields or instance member fields directly with little computation.

所以我有2个问题:

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

@StephenC

JVM是1.6.0_20(以前是1.6.0_0),在Solaris上运行.我知道是由多种原因引起问题的编译.

The JVM is 1.6.0_20 (previously 1.6.0_0), running on Solaris. I know it's the compilation that is causing a problem for a couple reasons.

  1. ps在它显示的秒数中显示,具有与编译器线程相对应的id(来自jstack)的java线程正在占用100%的CPU时间
  2. jstack显示问题出在JavaThread "CompilerThread1" daemon [_thread_in_native, id=34, ...]
  1. ps in the seconds leading up to it shows that a java thread with id corresponding to the compiler thread (from jstack) is taking up 100% of the CPU time
  2. jstack shows the issue is in JavaThread "CompilerThread1" daemon [_thread_in_native, id=34, ...]

jstack中提到的方法始终是相同的,并且是我们编写的方法.如果查看示例jstack输出,您将理解我的意思,但是出于明显的原因,我无法提供代码示例或文件名.我会说这是一个非常简单的方法. Essentiall进行了少量的空检查,2个执行相等性检查并可能分配值的循环,以及一些简单的方法调用.总共可能有40行代码.

The method mentioned in jstack is always the same one, and is one we wrote. If you look at sample jstack output you will know what I mean, but for obvious reasons I can't provide code samples or filenames. I will say that it is a very simple method. Essentiall a handful of null checks, 2 for loops that do equality checks and possibly assign values, and some simple method calls after. All in all maybe 40 lines of code.

尽管该应用每天运行并每天重新启动,但该问题在2周内已发生2次.此外,在任何时候,应用程序都不会承受重负载.

This issue has happened 2 times in 2 weeks, though the application runs every day and is restarted daily. In addition, the application wasn't under heavy load any of these times.

推荐答案

您可以通过创建一个名为.hotspot_compiler的文件并将其放在应用程序的工作目录"中,将特定方法排除在JIT之外.只需以以下格式在文件中添加一个条目:

You can exclude a particular method from being JIT'ed by creating a file called .hotspot_compiler and putting it in your applications 'working directory'. Simply add an entry in the file in the following format:

exclude com/amir/SomeClass someMethod

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

And the console output from the compiler will look like:

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

有关更多信息,请阅读.如果不确定应用程序的工作目录"是什么,请使用

For more information, read this. If you're not sure what you're applications 'working directory' is, use the

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

在Java启动脚本或命令行中.

in your Java start script or command line.

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

Alternatively, if you're not sure its the JIT compilers fault, and want to see if you can reproduce the problem without any JIT'ing, run your Java process with -Xint.

这篇关于Java JIT编译器导致OutOfMemoryError的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆