捕获Java内存泄露 (二)
来源:互联网 发布:适合笔记本的linux 编辑:程序博客网 时间:2024/06/05 00:17
原文:Hunting Memory Leaks in Java
上一篇:捕获Java内存泄露 (一)
捕获Java内存泄露 (二)
解密OutOfMemoryError
如上所述,OOM是内存泄漏的常见标志。本质上,是空间不足已分配新对象会引发此错误.。尽管百般努力,垃圾回收器依然找不到所需的空间,堆也不能进一步扩展。因此,stacktrace和错误一起被抛出。
诊断你的OOM的第一步是确定这个错误的确切意味。这听起来很明显,但答案并不总是那么清晰。例如:这个OOM出现是因为java堆已满,或者因为本地堆已满?为了帮助你回答这个问题,让我们分析几个可能的错误信息:
java.lang.OutOfMemoryError: Java heap space
java.lang.OutOfMemoryError: PermGen space
java.lang.OutOfMemoryError: Requested array size exceeds VM limit
java.lang.OutOfMemoryError: request <size> bytes for <reason>. Out of swap space?
java.lang.OutOfMemoryError: <reason> <stack trace> (Native method)
“Java heap space”
这条错误消息不一定意味着内存泄漏。其实,问题可能仅仅是配置错误。
例如,我曾经负责分析一个应用,它一直产生这种类型的OutOfMemoryError
。经过一番调查,我发现罪魁祸首是一个数组的实例化请求了太多的内存;在这种情况下,它并不是应用程序的问题,而是应用服务器只配置了默认堆的大小,它太小了。我通过调整JVM的内存参数解决了这个问题。
在其他情况下,特别是对于长寿命的应用程序,消息可能表明我们无意中持有对象的引用,阻止垃圾收集器清理它们。这是Java语言相当于一个内存泄漏。(注意:被应用程序调用的API也可能成为被无意中持有对象引用。)
另一个这种“java堆空间“OOM的潜在来源是finalizers的使用。如果类有finalize方法,则该类型的对象在垃圾回收时没有使它们的空间被回收。相反,在垃圾收集之后,这些对象排队等待后续的终结。在Sun的实现里,finalizers是由一个守护线程执行。如果finalizers线程不能跟上终结队列,然后java堆会被填满然后一个OOM被抛出。
“PermGen space”
此错误消息表示永久代(permanent generation)已满。永久代是存储类和方法对象的堆的区域.。如果一个应用程序要加载大量的类,那么永久代的大小可能需要使用-XX:MaxPermSize
选项来增加。
驻留的java.lang.String
对象也存储在永久代。java.lang.String
类维护一个字符串池。当调用intern()
方法时,该方法将检查池以查看是否存在等效字符串.。如果是,则由intern()
方法返回;如果没有,则将字符串添加到池中。更精确的描述是,java.lang.String.intern
方法返回一个字符串的规范表示(canonical representation);这个结果是对相同的类的实例的引用,如果该字符串是一个字面量。如果一个应用驻留了大量的字符串,你可能需要增加永久代的大小。
译者注:上述观点适用于Java6,且Java6早期版本中字符串池大小不可配置,自Java7之后,字符串池移回到了堆中,并且池大小可以通过
-XX:StringTableSize=N
选项来配置。
注意:你可以使用jmap - permgen
命令打印的永久代相关的统计信息,包括驻留的字符串实例信息。
“Requested array size exceeds VM limit”
此错误表示应用程序(或该应用程序使用的APIs)试图分配超出堆大小的数组。例如,如果应用程序试图分配512MB的数组,但堆的最大尺寸是256MB,那么一个带有这个错误信息的OOM将被抛出。在大多数情况下,这要么是配置问题要么是应用程序试图分配巨大的数组时产生的bug。
“Request <size> bytes for <reason>. Out of swap space?”
此消息看起来是一个OOM。但是,当在本地堆的一次分配失败,并且本地堆可能接近耗尽时,HotSpot VM会抛出这个明显的异常。消息中包含了请求并失败的大小(以字节为单位)和内存请求的原因.。在大多数情况下,<reason>是报告分配失败的源模块的名称。
如果这种类型的OOM被抛出,你可能需要在你的操作系统上使用故障排除工具来进一步诊断问题。在某些情况下,这个问题甚至可能与应用程序无关。例如,您可能会看到此错误如果:
- 操作系统配置的交换空间不足。
- 系统上的另一个进程正在消耗所有可用的内存资源。
应用程序也可能由于本地泄漏而失败(例如,如果某个应用程序或库代码正在连续分配内存,但未能将其释放回操作系统)。
“<reason> <stack trace> (Native method)”
如果您看到此错误消息,并且堆栈跟踪的第一帧是一个本地方法,那么那个本地方法遇到了分配失败。这一消息和以前的区别是:分配失败被检测到来自一个JNI或本地方法而不是java虚拟机代码。
如果这种类型的OOM被抛出,你可能需要在你的操作系统上使用故障排除工具来进一步诊断问题。
下一篇:捕获Java内存泄露 (三)
- 捕获Java内存泄露 (二)
- 捕获Java内存泄露 (一)
- 捕获Java内存泄露 (三)
- 捕获Java内存泄露 (四)
- 捕获Java内存泄露 (五)
- java内存泄露和内存溢出(二)
- VS2008中捕获内存泄露
- VS2008中捕获内存泄露
- VS2008中捕获内存泄露
- VS2008中捕获内存泄露
- VS2008中捕获内存泄露
- VS 中捕获内存泄露
- java内存泄露(1)
- java(7):内存泄露
- Android内存泄露调试(二)
- C++内存泄露的检测(二)
- Jprofile(二) - 查找内存泄露
- Android内存泄露 (二)
- 控制台下运行cl命令
- linux学习笔记--file命令
- URL简介(下)
- [技术]hibernate初步学习(一)
- qq邮箱发送
- 捕获Java内存泄露 (二)
- Android中的Loaders机制
- 未来的容器云技术栈会怎么样?
- 彻底弄懂 HTTP 缓存机制 —— 基于缓存策略三要素分解法
- Swift 之 UIImageView
- 手把手教你如何将图片“嵌入”网页中
- 深入函数
- Gradle学习笔记 Gradle命令行
- MFC中一些变量类型的转换和检查