Java.lang.OutOfMemoryError是什么
Java.lang.OutOfMemory是java.lang.VirtualMachineError的一个子类,当Java虚拟机中断,或是超出可用资源时抛出。很明显,OutOfMemory是在Java虚拟机资源耗尽的状况下没法分配对象时抛出的。不过很不幸,Java的说明文档并无对该异常进行进一步的阐述。
Java虚拟机包括六个不一样的运行时数据区域(内存区域):
1. 程序计数器(Program Counter Register)
2. Java虚拟机栈(Java VM Stack)
3. Java堆(Heap)
4. 方法区(Java VM Method Area)
5. 常量池(Runtime Constant Pool)
6. 本地方法栈(Native Method Stack)
程序计数器又称为PC寄存器,是存放当前正在被执行的Java 字节码操做指令的地址。 (这里加些说明: 对于一个运行中的Java 程序而言, 其中的每一个线程都有它本身的PC(程序计数器)寄存器,它是在该线程启动时建立的。PC寄存器的大小是一个字长,所以它既可以持有一个本地指针,也可以持有一个return Address.)
Java虚拟机栈是由栈帧(stack frame)组成,帧则是用来存储线程在执行过程当中的参数,返回值,以及中间结果等。若是在没有足够的内存给Java VM栈,或者没足够的内存来生成新的线程时,Java虚拟机将抛出OutOfMemoryError。
Heap是用来存储Java类实例或数组的。当没有足够的内存给新生实例或数组时,Java虚拟机将抛出OutOfMemoryError。
方法区则是用来存储类型相关的信息, 如该类型的常量池,字段或方法信息。当方法区没有足够内存时也会出现OutOfMemoryError。(这里加些说明: 类型中的类(静态)变量一样也是存储在方法区中,一个到ClassLoader的引用,一个到Class类的引用)
运行时常量池包括字段引用以及常量。当常量池没有足够内存可用时, 一样会抛出OutOfMemoryError异常。
本地方法区是由一些C/C++写的方法,给予JVM的一些方法支持。 同理,当没有可用内存时也会抛出OutOfMemoryError异常。
您可能看到一个与OutOfMemoryError彻底不同的异常:StackOverflowError。 该异常的抛出则是当本地内存栈或者Java虚拟机栈超出配置大小时抛出。 在大多数IBM 的Java虚拟机中,-Xmso命令参数能够控制操做系统栈线程和本地线程栈大小, -Xss参数能够控制Javs虚拟机的线程栈大小。 在一些如Sun HotSpot的JVM厂商, Java方法经过C/C++本地指令共享栈帧. –Xss能够为一个线程配置最大内存,该值的默认值和平台,以及具体JVM的实现厂商有关,但通常都在256K-1024K的大小. 请参考你的JVM说明文档。 在另外文章中咱们会涉及更多关于StackOverflowError的东西。
如今, 咱们了解了哪些内存区域会引发java.lang.OutOfMemory,让咱们来看看这个实际错误信息,该异常像如下哪一种,咱们又该如何去处理它们呢?
java
该例外代表有一数组请求一个超过VM预先分配的内存大小的内存值。 若是咱们遇到该类异常咱们该怎么办?咱们须要检出源码,以确保确实没有动态或静态的建立如此之大的数组。 不过还好,最后版本的VM通常不会有这样的限制。
数组
当Java Heap 中的Perm 内存区满的时候,JVM会抛出上面的同样的异常。
在一些Java虚拟机中, 如Sun 公司的HotSpot Java虚拟机, 一块存储类对象或方法对象的专有内存称为永久一代(又称永久区域)。咱们能够想象一下IBM 建模和分析工具的Java GC的perm 区使用方法。
在图中,咱们看到”Max Perm”和”Used Tenured”两按钮显示了Perm 区的使用方法和它的最大长度。咱们能够看到Perm区使用的总内存已经到了它的最大化上限,这就是为何咱们会获得 java.lang.OutOfMemoryError: PermGen Space 的异常. 假使没有内存泄露, 咱们能够经过调整-XX:MaxPermSize参数选项来增长Perm 区的最大化上限值。 好比这样:
-XX:MaxPermSize=128m
上面选项将设置Perm 区的最大值为128Mbytes.
Okay,到如今咱们已经看到因为耗尽Java Heap或者Java Heap中的Perm区的内存而致使抛出的Java.lang.OutOfMemoryError异常。不过更为意外的是, 当Java虚拟机在本地内存中, 找不到更多可用内存时, 仍然能够像在Java Heap中, 抛出Java.langOutOfMemory异常。那么在这种状况下, 咱们如何来判定该异常是从Java Heap中仍是本地内存中引起的呢 ?
在下面的异常中, 没有啥信息指定该OutOfMemoryError异常是从Java Heap仍是本地内存中抛出: 工具
如下异常,Java 虚拟机很是友好的告诉咱们足够的信息说是本地内存耗尽, 在该异常中, JVM描述到 “allocatedMemory failed”,这说明本地内存分配失败:
Java.lang.OutOfMemoryError: JVMCI026: allocatedMemory failed
如下异常,彷佛没啥线索可以说明是本地内存仍是Java Heap中抛出的异常,不过幸运的是咱们有一个行号,20,还有一个源文件的文件名, HeapExhaustionSimulator.java,好像是和Heap相关的,呵: spa
如下异常,彷佛仍然没啥线索可以说明是本地内存仍是Java heap中抛出。不过”sun.misc.Unsafe.allocatedMemory(Native Method)”代表彷佛是本地内存相关的。 操作系统
如下异常, Java 虚拟机指定Java Heap 中抛出java.lang.OutOfMemoryError. 线程
你以往可能见过像这样的一个异常: 指针
从字面上, 您可能会检查操做系统的swap 的配置大小,不过JVM彷佛也不肯定swap space 是否是最主要的缘由。咱们能够检查一下JVM是否已经使用了大量的本地内存, 咱们还需肯定有足够的内存提供给JVM,以及没有其余进程正在耗尽大量的内存资源。最后咱们有必要尝试找一些MMMM相关的bug。
对象
这样的异常是在说,若是您拥有大量的线程,或者本地内存耗尽时,新的线程企图建立时抛出。
Java Heap Dump 是什么?
咱们知道Java Heap 是全部类实例和数组对象分配的一个运行时数据区,其间全部Java VM线程在执行期间共享Heap 中的数据。那么一个Java heap dump至关于在一个特殊的时间点上生成的一个快照,它就像给一个繁忙的数据仓库在给定的时间上来了一个照片,咱们经过这张快照能够识别哪些组件在那快照的那时间点上是可用的。
因为Java 说明文档并无说起到Java heap dump,在各个不一样的JVM厂商,存在各个对Java heap dump的介绍。 如IBM JVM的Java heap dump 提供的信息大至和Java Heap差很少。
Sun公司提供的信息基本上是JVM Stack,运行时常量池和Java Heap等.
如何生成Java Heap Dumps ?
Java Heap Dumps一般是由JVM自动生成,不过您也能够强制生成Java Heap Dumps。在大多数IBM的JVM上。Java Heap Dumps 在当Java Heap 用完前自动生成。在大多数Sun 公司的JVM上,你须要在JVM上配置以生成Java Heap dumps. 若是你想在java.lang.OutOfMemory出现时生成,你须要在某些Sun的发行版的JVM配置 –XX:+HeapDumpOnOutOfMemoryError 参数选项. 你一样须要配置 –agentlib:phrof=heap=dump选项来使用HPROF。若是JVM提供, 你可使用jmap工具, 好比:jmap –dump 1234 将从进程号1234上生成Java heap dump. 你能够经过调用HotSpotDiagnostic MBean和dumpHeap 来利用JConsole来监视内存。
若是你想在IBM的JVMs上给JVM崩溃或是用户信号生成Java heap dumps, 你能够配置环境变量 IBM_HEAPDUMP和IBM_HEAP_DUMP置为TRUE. 如:能够在给IBM JVM发送一个SIGQUIT信号
具体请参阅你的JVM说明文档以得到更多信息,由于因为平台与厂商的不一样,选项会有所变化。
在哪能够找到Java Heap Dumps ?
您能够在JVM进程的当前工做目录下找到Java heap dumps,除非你指定了另外的目录位置。
您能够在IBM JVMs上经过环境变量指定目录位置: IBM_HEAPDUMPDIR 和 _CEE_DEPTARG.
若是没有足够的空间给指定的目录,或JVM在指定目录下未获取写权限, Java Heap dumps 将会在操做系统的临时目录下生成。 关于操做系统的默认临时目录位置和配置信息,请参阅你的操做系统手册。 进程