简体   繁体   English

如何判断java应用程序是否接近内存不足

[英]How to tell if java application is close to running out of memory

My simple goal: monitor the memory usage of a Java application so I can be warned when the application is getting dangerously close to throwing an OutOfMemoryError . 我的简单目标:监视Java应用程序的内存使用情况,以便在应用程序危险地接近抛出OutOfMemoryError时收到警告。

Yes, simple to state, but coming up with a correct solution seems very complicated. 是的,简单说明,但提出正确的解决方案似乎非常复杂。 Some of the complicating factors are: 一些复杂因素是:

  • There are different heap regions, each of which can throw an OutOfMemoryError : 有不同的堆区域,每个堆区域都可以抛出OutOfMemoryError
    • The permgen space, which has it's own size limit (set via -XX:MaxPermSize= ) permgen空间,它有自己的大小限制(通过-XX:MaxPermSize=
    • The overall heap space (set via -Xmx ) 整个堆空间(通过-Xmx设置)
  • The VM may allocate almost all of the heap before bothering to garbage collect. 在烦扰垃圾收集之前,VM可能会分配几乎所有堆。 If the application uses a lot of soft references, then in fact this will surely happen. 如果应用程序使用了很多软引用,那么事实上肯定会发生这种情况。 So just a high heap allocation percentage does not imply the application is near to throwing an OutOfMemoryError . 因此,只有高堆分配百分比并不意味着应用程序接近抛出OutOfMemoryError
  • It would be nice if System.gc() guaranteed that the VM would reclaim all possibly reclaimable object (unreferenced and/or weakly referenced object), but it doesn't. 如果System.gc()保证VM将回收所有可能可回收的对象(未引用和/或弱引用的对象),那将是很好的,但事实并非如此。 So invoking System.gc() and then Runtime.freeMemory() is not reliable. 因此调用System.gc()然后调用Runtime.freeMemory()是不可靠的。
  • Objects that are queued for finalization take up memory, but (usually) are freed after they are finalized. 排队等待最终确定的对象占用内存,但(通常)在完成后将被释放。 So whether the finalizer thread has gotten to them or not affects the (apparent) memory usage (does the VM run the finalizer as a last desparate act before throwing OOM? Doesn't look like it. ) 那么终结器线程是否已经到达它们会影响(明显的)内存使用量(在抛出OOM之前,VM是否将终结器作为最后一个绝对的行为运行? 看起来不像它。
  • Native code takes up memory as well and too much usage of it can lead to OOM (this is not a likely case in my specific application, but does add another complication to the overall picture). 本机代码也会占用内存,过多使用它会导致OOM(在我的特定应用程序中这不是一个可能的情况,但确实会给整个图片增加另一个复杂性)。

So what is a good and reliable way to answer the question: Is my Java application getting to throwing an OutOfMemoryError ? 那么回答这个问题的好方法是什么呢?我的Java应用程序是否会抛出OutOfMemoryError

Put another way, suppose application version X runs fine and has no memory leak, but version X + 1 has a slow unrecognized memory leak. 换句话说,假设应用程序版本X运行良好且没有内存泄漏,但版本X + 1具有缓慢的无法识别的内存泄漏。 I'd like to be alerted by this monitoring before version X + 1 throws an OutOfMemoryError , but I'd like the exact same monitoring to not give false positives for version X. There may be some tuning required in setting up this monitoring - that's OK. 我希望在版本X + 1抛出OutOfMemoryError之前通过此监视提醒我,但我希望完全相同的监视不会给版本X带来误报。设置此监视可能需要一些调整 - 这是好。

One possible answer might be something like: what is the maximum, over the past N "full" GC runs, of the heap utilization immediately after the GC run? 一个可能的答案可能是这样的结果:在GC运行之后,堆栈利用率在过去的N次“完整”GC运行中的最大值是多少? If this value exceeds X% of the total allocated memory, then sound the alarms. 如果此值超过总分配内存的X%,则发出警报声。

The idea is to determine "application memory usage" in simple number like a percentage, or even something like LOW, MEDIUM, or HIGH, and then monitor this value. 这个想法是确定“应用程序内存使用”的简单数字,如百分比,甚至像LOW,MEDIUM或HIGH,然后监视此值。

The jstat command gives lots of relevant information, the problem is boiling it down to a simple answer and avoiding false positives (or negatives) caused by the complicating factors listed above. jstat命令提供了大量相关信息,问题是将其简化为一个简单的答案,并避免由上面列出的复杂因素引起的误报(或否定)。

If you watch a memory graph of a long-running application (collected with a tool like jconsole, for example) you'll see a characteristic sawtooth pattern: memory usage climbs, then is GC'd back to a baseline, and then it climbs again. 如果您观看长时间运行的应用程序的内存图(例如,使用像jconsole这样的工具收集),您将看到一个特征锯齿模式:内存使用率攀升,然后GC返回到基线,然后它爬升再次。 For a healthy app, the peaks and valleys are in two straight horizontal lines. 对于健康的应用程序,峰和谷是两条直线水平线。 For a leaking app, though, the baseline climbs. 然而,对于泄漏的应用程序,基线攀升。 That's really what you need to watch for: if each successive GC is less effective than the last, then something is rotten in Denmark. 这真的是你需要注意的:如果每个连续GC的效果都不如上一次,那么丹麦就会出现问题。

Search the Oracle docs page for the term Detecting Low Memory and Threshold Notifications -- you may be able to devise some alert system based upon built-in MXBeans. 在Oracle文档页面中搜索 Detecting Low MemoryThreshold Notifications这一术语 - 您可以设计一些基于内置MXBeans的警报系统。 Garbage collection appears to be a focus of at least some of the metrics collection. 垃圾收集似乎是至少一些指标集合的焦点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM