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代码

  1. Java.lang.OutOfMemoryError: Requested array size exceeds VM limit

[java] view plaincopy

  1. Java.lang.OutOfMemoryError: Requested array size exceeds VM limit

该例外表明有一数组请求一个超过VM预先分配的内存大小的内存值。 如果我们遇到该类异常我们该怎么办?我们需要检出源码,以确保确实没有动态或静态的创建如此之大的数组。 不过还好,最后版本的VM一般不会有这样的限制。

Java代码

  1. Java.lang.OutOfMemoryError : PermGen space

[java] view plaincopy

  1. Java.lang.OutOfMemoryError : PermGen space

当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代码

  1. JVMDUMP013I Processed dump event “systhrow”, detail “java/lang/OutOfMemoryError”.

[java] view plaincopy

  1. JVMDUMP013I Processed dump event “systhrow”, detail “java/lang/OutOfMemoryError”.

以下异常,Java 虚拟机非常友好的告诉我们足够的信息说是本地内存耗尽, 在该异常中, JVM描述到 “allocatedMemory failed”,这说明本地内存分配失败: 
Java.lang.OutOfMemoryError: JVMCI026: allocatedMemory failed

以下异常,似乎没啥线索能够说明是本地内存还是Java Heap中抛出的异常,不过幸运的是我们有一个行号,20,还有一个源文件的文件名, HeapExhaustionSimulator.java,好像是和Heap相关的,呵:

Java代码

  1. JVMDG274: Dump Handler has Processed OutOfMemory.
  2. Exception in thread "main" java.lang.OutOfMemoryError
  3. at HeapExhaustionSimulator.main(HeapExhaustionSimulator.java:20)

[java] view plaincopy

  1. JVMDG274: Dump Handler has Processed OutOfMemory.
  2. Exception in thread "main" java.lang.OutOfMemoryError
  3. at HeapExhaustionSimulator.main(HeapExhaustionSimulator.java:20)

以下异常,似乎仍然没啥线索能够说明是本地内存还是Java heap中抛出。不过”sun.misc.Unsafe.allocatedMemory(Native Method)”表明似乎是本地内存相关的。

Java代码

  1. Exception in thread "main" java.lang.OutOfMemoryError
  2. at sun.misc.Unsafe.allocateMemory(Native Method)
  3. at java.nio.DirectByteBuffer.<init>(DirectByteBuffer.java:99)
  4. at java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:288)
  5. at NativeMemorySimulator.main(NativeMemorySimulator.java:11)

[java] view plaincopy

  1. Exception in thread "main" java.lang.OutOfMemoryError
  2. at sun.misc.Unsafe.allocateMemory(Native Method)
  3. at java.nio.DirectByteBuffer.<init>(DirectByteBuffer.java:99)
  4. at java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:288)
  5. at NativeMemorySimulator.main(NativeMemorySimulator.java:11)

以下异常, Java 虚拟机指定Java Heap 中抛出java.lang.OutOfMemoryError.

Java代码

  1. java.lang.OutOfMemoryError: Java heap space
  2. Dumping heap to java_pid6280.hprof ...
  3. Heap dump file created [50549348 bytes in 1.444 secs]

[java] view plaincopy

  1. java.lang.OutOfMemoryError: Java heap space
  2. Dumping heap to java_pid6280.hprof ...
  3. Heap dump file created [50549348 bytes in 1.444 secs]

你以往可能见过像这样的一个异常:

Java代码

  1. java.lang.OutOfMemoryError: requested NNN bytes for MMMM. Out of swap space?

[java] view plaincopy

  1. java.lang.OutOfMemoryError: requested NNN bytes for MMMM. Out of swap space?

从字面上, 您可能会检查操作系统的swap 的配置大小,不过JVM似乎也不确定swap space 是不是最主要的原因。我们可以检查一下JVM是否已经使用了大量的本地内存, 我们还需确定有足够的内存提供给JVM,以及没有其他进程正在耗尽大量的内存资源。最后我们有必要尝试找一些MMMM相关的bug。

Java代码

  1. Java.lang.OutOfMemoryError: unable to create native thread

[java] view plaincopy

  1. Java.lang.OutOfMemoryError: unable to create native thread

这样的异常是在说,如果您拥有大量的线程,或者本地内存耗尽时,新的线程企图创建时抛出。 

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 将会在操作系统的临时目录下生成。 关于操作系统的默认临时目录位置和配置信息,请参阅你的操作系统手册。

时间: 2024-10-19 08:18:14

Java.lang.OutOfMemoryError是什么的相关文章

jvm 内存溢出 在myeclipse中加大tomcat的jvm内存 java.lang.OutOfMemoryError: PermGen space

使用myeclipse启动部署在tomcat7下的三个项目报出java.lang.OutOfMemoryError: PermGen space 解决办法: 在myeclipse中加大jvm内存方法:Window->Preferences->Myeclipse->Services->Tomcat->Tomcat 6.x->JDK,在Optional Java VM arguments:下边的输入框里输入:-Xms128m -Xmx512m -XX:PermSize=12

Java 内存溢出(java.lang.OutOfMemoryError)的常见情况和处理方式总结

最近老是遇见服务器内存溢出的问题,故在网上搜了搜,总结了一些java内存溢出的解决方式 java.lang.OutOfMemoryError这个错误我相信大部分开发人员都有遇到过,产生该错误的原因大都出于以下原因:JVM内存过小.程序不严密,产生了过多的垃圾. 导致OutOfMemoryError异常的常见原因有以下几种: 内存中加载的数据量过于庞大,如一次从数据库取出过多数据: 集合类中有对对象的引用,使用完后未清空,使得JVM不能回收: 代码中存在死循环或循环产生过多重复的对象实体: 使用的

Tomcat 优化 java.lang.OutOfMemoryError: Java heap space 的解决方法

java.lang.OutOfMemoryError: Java heap space 的解决方法 关键字: tomcat outofmemoryerror permgen space java heap space 最近在熟悉一个开发了有几年的项目,需要把数据库从mysql移植到oracle,首先把jdbc的连接指向mysql,打包放到tomcat里面,可以跑起来,没有问题,可是当把jdbc连接指向oracle的时候,tomcat就连续抛java.lang.OutOfMemoryError的错

Eclipse:java.lang.OutOfMemoryError: PermGen space

先是好端端的上不了网,然后电脑就重启,重启之后,整个项目就报"java.lang.OutOfMemoryError: PermGen space" 网上说了很多方法,什么修改eclipse.ini,修改tomcat bin目录下的catalina.sh文件,但是对我问题没有一点用处, 最后,解决方案如下: 记住一定要换行啊!

java.lang.OutOfMemoryError: Java heap space解决办法

//首先检查程序有没有限入死循环 这个问题主要还是由这个问题 java.lang.OutOfMemoryError: Java heap space 引起的.第一次出现这样的的问题以后,引发了其他的问题.在网上一查可能是JAVA的堆栈设置太小的原因. 跟据网上的答案大致有这两种解决方法: 1.设置环境变量 解决方法:手动设置Heap size 修改TOMCAT_HOME/bin/catalina.sh set JAVA_OPTS= -Xms32m -Xmx512m 可以根据自己机器的内存进行更改

java.lang.OutOfMemoryError:GC overhead limit exceeded

之所以写下来,是因为不想在下次遇到事有到处找,很多时候错误信息一样,但是导致的原因却有很多. 我试驾了一个虚拟机启动采纳数:-XX:-UseGCOverheadLimit 把原文链接写上,标示感谢: http://www.cnblogs.com/hucn/p/3572384.html 我遇到这样的问题,本地部署时抛出异常java.lang.OutOfMemoryError:GC overhead limit exceeded导致服务起不来,查看日志发现加载了太多资源到内存,本地的性能也不好,gc

异常处理系列:java.lang.OutOfMemoryError: PermGen space

今天帮同学解决他的Tomcat启动的问题,报出了一个OutOfMemoryError的异常,然后就搜啊搜的,突然发现特别有趣. 先不扯淡了,先说解决办法: 一看到这个就知道是内存满了.所以要把Tomcat的内存池加大一点. 修改如下: 1. window-->Preferences,然后直接在搜索的那个框里边写上"tomcat",会出现如下的界面: 2. 选中你安装的tomcat版本,选中下面的JDK,在右边的 Optional Java VM arguments 文本框中输入:

从[java.lang.OutOfMemoryError: Java heap space]中恢复

出现java.lang.OutOfMemoryError: Java heap space的错误要么是程序问题,要么就是分配给JVM的内存确实不够. 一般来说都是可以事前可控解决的. 但是如果不可控的情况,例如使用第三方包,或者系统抽筋,就会抛出OutOfMemoryError错误.OH NO,根据不会抛出来,当前线程直接挂掉. 既然都挂掉了,谈什么恢复?而且挂掉也不只是OutOfMemoryError的问题. 一般情况下,OutOfMemoryError在不可控的情况下,真的真的真的不需要处理

Eclipse运行程序提示:Exception in thread &quot;main&quot; java.lang.OutOfMemoryError: Java heap space

问题描述: Exception in thread "main" java.lang.OutOfMemoryError: Java heap space 问题原因: 程序中对象引用过多导致堆空间不足,导致内存溢出 解决方案: (增大Java虚拟机的内存空间) 打开Eclipse,选择"Run" - "Run Configurations" - "(x)=Arguments",VM arguments栏中填写 -Xmx800m

java.lang.OutOfMemoryError: PermGen space---先测试

一.在window下eclipse里面Server挂的是tomcat6,一开始还是以为,tomcat配置的问题,后面发现,配置了tomcat里面的catalina.bat文件,加入 set JAVA_OPTS=-Xms512m -Xmx1024m -XX:PermSize=256M -XX:MaxNewSize=108m -XX:MaxPermSize=512m ,eclipse跑起来还是报Java.lang.OutOfMemoryError: PermGen space. 后面在网上找了资料,