内容参考:
https://docs.oracle.com/javase/7/docs/webnotes/tsg/TSG-VM/html/memleaks.html
内存泄漏的一个常见迹象是java.lang.OutOfMemoryError错误。当Java堆或堆的特定区域中没有足够的空间分配对象时,将引发此错误。垃圾收集器无法提供更多空间来容纳新对象,并且堆无法进一步扩展。
抛出java.lang.OutOfMemoryError错误时,也会打印堆栈跟踪。
当无法满足本机分配时(例如,如果交换空间不足),本机库代码也可以抛出java.lang.OutOfMemoryError。
1、Java heap space
Exception in thread "main": java.lang.OutOfMemoryError: Java heap space
详细消息Java heap space指示无法在Java堆中分配对象。此错误不一定意味着内存泄漏。这个问题可以简单到配置问题,即指定的堆大小(如果未指定,则为默认大小)不适合应用程序。
在其他情况下,尤其是对于长寿命的应用程序,消息可能表示应用程序无意中保存了对对象的引用,这将防止对对象进行垃圾收集。这相当于Java语言中的内存泄漏。注意,应用程序调用的api也可能无意中保存对象引用。
OutOfMemoryError的另一个潜在来源是过度使用终结器的应用程序。如果类具有finalize方法,则在垃圾收集时,该类型的对象的空间不会被回收。相反,在垃圾回收之后,对象将排队等待完成,这将在稍后发生。在Sun实现中,终结器由为终结队列提供服务的守护进程线程执行。如果终结器线程无法跟上终结队列,那么Java堆可能会填满,并抛出OutOfMemoryError。可能导致这种情况的一种情况是,应用程序创建高优先级线程,导致终结队列以比终结器线程为该队列提供服务的速率更快的速率增长。
2、PermGen space
Exception in thread "main": java.lang.OutOfMemoryError: PermGen space
详细消息PermGen space表示永久带已满。永久带是堆中存储类和方法对象的区域。如果应用程序加载大量类,那么可能需要使用-XX:MaxPermSize选项增加永久带的大小。
内部的java.lang.String对象不再存储在永久带中。String类维护一个字符串池。调用intern方法时,该方法检查池中是否已存在相等的字符串。如果存在,则intern方法返回它;否则,它会将字符串添加到池中。更准确地说,java.lang.String.intern方法用于获取字符串的规范表示;结果是对同一个类实例的引用,如果该字符串显示为文本,则将返回该实例。
当发生此类错误时,文本ClassLoader.defineClass可能会出现在打印的堆栈跟踪的顶部附近。
jmap-permgen命令打印永久带中对象的统计信息,以及有关内部化字符串实例的信息。
3、Requested array size exceeds VM limit
Exception in thread "main": java.lang.OutOfMemoryError: Requested array size exceeds VM limit
请求的数组大小超过VM限制的详细消息表示应用程序(或该应用程序使用的api)试图分配大于堆大小的数组。例如,如果应用程序试图分配512MB的数组,但最大堆大小为256MB,则会抛出OutOfMemoryError,原因是请求的数组大小超过VM限制。在大多数情况下,问题要么是配置问题(堆大小太小),要么是导致应用程序试图创建一个巨大数组的错误(数据库全表查询),例如,当使用计算错误大小的算法计算数组中的元素数时。
4、Detail Message: request <size> bytes for <reason>. Out of swap space?
Exception in thread "main": java.lang.OutOfMemoryError: request <size> bytes for <reason>. Out of swap space?
详细消息请求<size>字节,原因是<reason>。交换空间不足?似乎是OutOfMemory错误。但是,当本机堆的分配失败并且本机堆可能接近耗尽时,HotSpot VM代码会报告这个明显的异常。消息指示失败的请求的大小(字节)和内存请求的原因。在大多数情况下,消息的<reason>部分是报告分配失败的源模块的名称,尽管在某些情况下它指明了原因。
当抛出此错误消息时,VM调用致命错误处理机制,即生成致命错误日志文件,其中包含有关崩溃时线程、进程和系统的有用信息。在本机堆耗尽的情况下,日志中的堆内存和内存映射信息可能很有用。
该问题可能与应用程序无关,例如:
操作系统配置的交换空间不足。
系统上的另一个进程正在消耗所有内存资源。
如果以上两个问题都不是原因,则应用程序可能由于本机泄漏而失败,例如,应用程序或库代码正在连续分配内存,但没有将其释放到操作系统。
5、Detail Message: <reason> <stack trace> (Native method)
Exception in thread "main": java.lang.OutOfMemoryError: <reason> <stack trace> (Native method)
如果错误消息的详细信息部分是<reason><stack trace>(本机方法),并且打印了顶部框架是本机方法的堆栈跟踪,则这表示本机方法遇到分配失败。此消息与上一条消息的区别在于,分配失败是在JNI或本机方法中检测到的,而不是在Java VM代码中检测到的。
如果抛出此类OutOfMemoryError,则可能需要使用操作系统上的实用程序来进一步诊断该问题。
网友评论