Java内存泄露常见类型及对应相关JVM参数

jvm
Java 网络应用 JBoss JVM Bean
  昨天晚上启动jboss之后,发现点击某个页面,总是crash掉;控制台信息如下:
----------------------------------------------------------------------------------------------------------------
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x6dd1a7a1, pid=6044, tid=2744
#
# JRE version: 6.0_22-b04
# Java VM: Java HotSpot(TM) Server VM (17.1-b03 mixed mode windows-x86 )
# Problematic frame:
# V  [jvm.dll+0x1aa7a1]
#
# If you would like to submit a bug report, please visit:
#   http://java.sun.com/webapps/bugreport/crash.jsp
#
----------------------------------------------------------------------------------------------------------------
  后来同事将他的JOBSS给我,当时是OK了,同事说是JVM启动参数不一样,当时也没有深究;结果今天早上上来在什么都没有修改的情况下,居然又crash了;乘着这个加深学习了下JVM的一些参数配置知识。
(一)产生错误的原因
造成严重错误的原因有多种可能性。Java虚拟机自身的Bug是原因之一,但是这种可能性很小。在绝大多数情况下,是由于系统的库文件、API或第三方的库文件造成的;或者是系统资源的短缺也有可能造成这种严重的错误。
(二).对日志文件的分析
日志头中“EXCEPTION_ACCESS_VIOLATION ”标明了日志错误类型。一般还有另外一种常见的错误类型:EXCEPTION_STACK_OVERFLOW;
日志中另外一个有用的信息就是:
# Problematic frame:
# V  [jvm.dll+0x1aa7a1]
它说明Crash的时候,JVM正在从哪个库文件执行代码。除了“V”以外,还有可能是“C”、“j”、“v”、“J”。具体的表示意思如下:
FrameType Description:
C: Native C frame
j: Interpreted Java frame
V: VMframe
v: VMgenerated stub frame
J: Other frame types, including compiled Java frames
EXCEPTION_ACCESS_VIOLATION加上“ # Problematic frame: # V [jvm.dll+....”说明一般是内存回收引起的问题。对于内存回收的错误,一 般采取改变回收的算法和参数的方法来绕过去。改变内存回收的算法,或者优化JVM配置参数来解决。
所以在本次错误中,优化JBOSS中JVM的启动参数可以解决问题。但是为什么一模一样的配置,昨天晚上OK的,今天早上却失败了?具体的我现在也没有明确的答案,我猜测可能是在特定的条件下(比如说本机的系统资源,远程调用的系统稳定性,以及网络是否繁忙等都可能会产生影响)产生的。
(三).其他常见错误 

年老代堆空间被占满

1.java.lang.OutOfMemoryError: Java heap space
当设置JBOSS启动参数:
set JAVA_OPTS=%JAVA_OPTS% -Xms128m -Xmx128m
后台日志报错:
Java代码 复制代码  收藏代码
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'xxxAO' defined in resource loader resource [/xxx/biz/bean/biz-xx.xml]: Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'xxxServices' defined in resource loader resource [/xxx/biz/bean/biz-xxx.xml]: Invocation of init method failed; nested exception is java.lang.OutOfMemoryError: Java heap space  
</pre><span style="font-weight: bold;">说明:</span> 这里是指最大堆内存设置太小,可以通过设置JBOSS启动参数:–Xmx 增加堆内存即可; </div><div class="bct fc05 fc11 nbw-blog ztag"><p>这是最典型的内存泄漏方式,简单说就是所有堆空间都被无法回收的垃圾对象占满,虚拟机无法再在分配新空间。</p><p>    如上图所示,这是非常典型的内存泄漏的垃圾回收情况图。所有峰值部分都是一次垃圾回收点,所有谷底部分表示是一次垃圾回收后剩余的内存。连接所有谷底的点,可以发现一条由底到高的线,这说明,随时间的推移,系统的堆空间被不断占满,最终会占满整个堆空间。因此可以初步认为系统内部可能有内存泄漏。(上面的图仅供示例,在实际情况下收集数据的时间需要更长,比如几个小时或者几天) </p><p><strong>解决:</strong></p><p>    这种方式解决起来也比较容易,一般就是根据垃圾回收前后情况对比,同时根据对象引用情况(常见的集合对象引用)分析,基本都可以找到泄漏点</p><p></p><p></p><p><span style="color: rgb(0, 0, 255);"><strong><span style="font-size: 14px;"><span style="color: rgb(0, 0, 255); font-size: 14px; "><strong>GC回收时间过长</strong></span></span></strong></span></p><span style="color: rgb(255, 0, 0);"><span style="font-size: 14px;">2.<span style="color: rgb(255, 0, 0); font-size: 14px;">java.lang.OutOfMemoryError: GC overhead limit exceeded</span></span></span></div><div class="bct fc05 fc11 nbw-blog ztag">当设置JBOSS启动参数: set JAVA_OPTS=%JAVA_OPTS% -Xms128m –Xmx256m 日志错误: Java代码 <a target=_blank target="_blank" title="复制代码" rel="nofollow" href="http://scholers.iteye.com/blog/856168#"><img title="Java内存泄露常见类型及对应相关JVM参数 - 火木棉 - 淡泊明智" alt="复制代码" src="https://i-blog.csdnimg.cn/blog_migrate/302d4eaa519c22050e243ddbad809cb6.gif" /></a> <img title="Java内存泄露常见类型及对应相关JVM参数 - 火木棉 - 淡泊明智" alt="收藏代码" src="https://i-blog.csdnimg.cn/blog_migrate/112f4b4df966813b576b0f7f4f702dc4.png" />java.lang.OutOfMemoryError: GC overhead limit exceeded  <pre code_snippet_id="120869" snippet_file_name="blog_20131220_1_7805684" title="JAVA应用Crash错误分析" pre_index="1" source_url="http://scholers.iteye.com/blog/856168" codeable_type="Blog" codeable_id="856168" name="code">

说明:
意味着太多的时间花在了垃圾收集上面,SUN的建议是指定垃圾回收的算法, 加上启动参数-XX:-UseGCOverheadLimit,从而限制JVM在抛出OutOfMemoryError之前限制其耗费在GC上的时间。
GC overhead limt exceed检查是Hotspot VM 1.6定义的一个策略,通过统计GC时间来预测是否要OOM了,提前抛出异常,防止OOM发生。Sun 官方对此的定义是:“并行/并发回收器在GC回收时间过长时会抛出OutOfMemroyError。过长的定义是,超过98%的时间用来做GC并且回收了不到2%的堆内存。用来避免内存过小造成应用不能正常工作。“

解决:

    1. 增加参数,-XX:-UseGCOverheadLimit,关闭这个特性

    2. 同时增加heap大小,-Xmx1024m



持久代被占满

3.java.lang.OutOfMemoryError: PermGen space
这一部分用于存放Class和Meta的信息,Class在被 Load的时候被放入PermGen space区域,它和和存放Instance的Heap区域不同,GC(Garbage Collection)不会在主程序运行期对PermGen space进行清理,所以 如果你的APP会LOAD很多CLASS的话,就很可能出现PermGen space错误。
解决方法: 手动设置MaxPermSize大小 

说明:

    Perm空间被占满。无法为新的class分配存储空间而引发的异常。这个异常以前是没有的,但是在Java反射大量使用的今天这个异常比较常见了。主要原因就是大量动态反射生成的类不断被加载,最终导致Perm区被占满。

    更可怕的是,不同的classLoader即便使用了相同的类,但是都会对其进行加载,相当于同一个东西,如果有N个classLoader那么他将会被加载N次。因此,某些情况下,这个问题基本视为无解。当然,存在大量classLoader和大量反射类的情况其实也不多。

解决:

    1. -XX:MaxPermSize=16m

    2. 换用JDK。比如JRocket。


堆栈溢出

4:java.lang.StackOverflowError

说明:这个就不多说了,一般就是递归没返回,或者循环调用造成

 

 

线程堆栈满

5:Fatal: Stack size too small

说明:java中一个线程的空间大小是有限制的。JDK5.0以后这个值是1M。与这个线程相关的数据将会保存在其中。但是当线程空间满了以后,将会出现上面异常。

解决:增加线程栈大小。-Xss2m。但这个配置无法解决根本问题,还要看代码部分是否有造成泄漏的部分。

 

系统内存被占满

6:java.lang.OutOfMemoryError: unable to create new native thread

说明

    这个异常是由于操作系统没有足够的资源来产生这个线程造成的。系统创建线程时,除了要在Java堆中分配内存外,操作系统本身也需要分配资源来创建线程。因此,当线程数量大到一定程度以后,堆中或许还有空间,但是操作系统分配不出资源来了,就出现这个异常了。

分配给Java虚拟机的内存愈多,系统剩余的资源就越少,因此,当系统内存固定时,分配给Java虚拟机的内存越多,那么,系统总共能够产生的线程也就越少,两者成反比的关系。同时,可以通过修改-Xss来减少分配给单个线程的空间,也可以增加系统总共内生产的线程数。

解决:

    1. 重新设计系统减少线程数量。

    2. 线程数量不能减少的情况下,通过-Xss减小单个线程大小。以便能生产更多的线程。



另外:
JBOSS启动参数说明
-Xms256m 初始的java内存堆大小 256M
-Xmx2048m 最大的java内存堆大小 2048M
-XX:PermSize=128m GC预留的内存,如果你的应用有大量的Class被动态载入或卸载,你应该不这个参数设大些
-XX:MaxPermSize=256m 最大的GC预留内存
-Dsun.rmi.dgc.client.gcInterval=3600000 RMI客户端GC发生周期的设定
-Dsun.rmi.dgc.server.gcInterval=3600000 RMI服务端GC发生周期的设定
参考资料:
http://blog.csdn.net/sfdev/archive/2008/01/24/2063928.aspx
http://developers.sun.com.cn/blog/yutoujava/entry/20070411#comments
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值