java内存溢出之permgenoom

上传人:xiao****1972 文档编号:84822274 上传时间:2019-03-05 格式:DOC 页数:9 大小:101.50KB
返回 下载 相关 举报
java内存溢出之permgenoom_第1页
第1页 / 共9页
java内存溢出之permgenoom_第2页
第2页 / 共9页
java内存溢出之permgenoom_第3页
第3页 / 共9页
java内存溢出之permgenoom_第4页
第4页 / 共9页
java内存溢出之permgenoom_第5页
第5页 / 共9页
点击查看更多>>
资源描述

《java内存溢出之permgenoom》由会员分享,可在线阅读,更多相关《java内存溢出之permgenoom(9页珍藏版)》请在金锄头文库上搜索。

1、Java内存溢出之PermGen OOM深入分析 朱兴 2008-3-28本文原作:http:/ 堆(heap)内存泄漏:大家都比较熟悉 2. 栈(stack)内存泄漏:当前线程运行期间维护的中间变量等信息过多,例如常见的死循环引起stack over flow 3. 方法区(permanent heap)内存泄漏:分析其原因的文章较少,本文的着重点。 网上关于讨论PermGen OOM的资料很多,但是深入分析PermGen区域内存溢出原因的资料很少。本篇文章尝试全面分析一下PermGen OOM的原因,其中涉及到了Java虚拟机运行时数据区、类型装载、类型卸载等,测试代码涉及到了JMX协议。

2、【相关知识】 1. Java类加载相关的知识,Java类加载原理简析中结合JDK的代码实现对Java类加载的原理做了比较深入的分析. 2. Java类型卸载相关的知识,Java虚拟机类型卸载和类型更新解析 中对结合Java虚拟机规范对虚拟机类型卸载和类型更新做了较为深入的分析,网址链接http:/ 3. 有关JMX协议可以参加sun公司发布的技术规范,对JMX协议做一定的了解对理解Java性能监控和调优功能的实现原理有很大帮助。 虚拟机运行时数据区介绍本部分将对Java虚拟机运行时数据区做一个简单的介绍,着重说明PermGen区域(永久存储区)存放的内容,并对运行时数据区的访问方式做一个归纳说

3、明,为后面深入分析类型卸载和PermGen OOM做铺垫。为了更具有通用性,本部分将更多关注虚拟机协议本身,可能和具体的虚拟机实现有少许的出入。运行时数据区分类Java虚拟机的运行时数据区一般分类如下(不一定是物理划分):1. 堆:主要存放对象实例,线程共享 2. 栈:主要存储特定线程的方法调用状态,线程独占 3. 本地方法栈:存储本地方法的调用状态,线程独占 4. PC寄存器:学过操作系统课程的都知道,线程独占 5. 方法区:主要存储了类型信息,线程共享 方法区可以简单的等价为所谓的PermGen区域(永久存储区),在很多虚拟机相关的文档中,也将其称之为永久堆(permanent heap)

4、,作为堆空间的一部分存在。介于此,我们可以简单说明一下我们常用的几个堆内存配置的参数关系:*-XX: PermSize:*永久堆(Pergen区域)大小默认值*-XX:MaxPermSize:*永久堆(Pergen区域)最大值*-Xms:*堆内存大小默认值*-Xmx:*堆内存最大值运行时数据区访问方式总结从开发者角度,虚拟机运行时数据区的访问方式简要归纳如下:1. 活动的线程可以通过对应的栈来访问运行时数据区信息 2. 栈是堆访问的入口 3. 堆上Java.lang.Class实例是访问PermGen区域中类型信息的入口 【示意图说明:】1. 一个类型装载之后会创建一个对应的java.lang

5、.Class实例,这个实例本身和普通对象实例一样存储于堆中,我觉得之所以说是这是一种特殊的实例,某种程度上是因为其充当了访问PermGen区域中类型信息的代理者。 2. 图中的Class类型实例和类加载器实例分别是A类型对应的java.lang.Class实例和加载A类型的类加载器实例。 3. 只要是有active的对象实例句柄,就能够访问到对应的Class类型实例和类加载器实例,分别通过Object.getClass()方法和Class.getClassLoader()方法。 4. 只要是有active的Class类型实例句柄,就能够访问到对应的类加载器实例。 PermGen内存溢出深入分析

6、在本部分,首先交代一下必要的前提知识,这也为理解后面的测试程序做铺垫。前提知识1. 由不同的类加载器实例加载的类型可以等价为完全不同的类型,哪怕时同一类型类加载器的不同实例加载的,都会在PermGen区域分配相应的空间来存储类型信息 2. 新类型加载时,会在PermGen区域申请相应的空间来存储类型信息,类型被卸载后,PermGen区域上的垃圾收集会释放对应的内存空间。PermGen区域和普通的堆空间一样,也遵循垃圾收集的规律,所以,网上很多资料种关于PermGen区域空间的大小是只增不减的说法是不正确的,后面会用相应的测试代码来验证和分析。 3. 一种类型被卸载的前提条件是:加载此类型的类加

7、载器实例变为不可达(unreachable)状态,虚拟机协议中对应描述如下:A class or interface may be unloaded if and only if its class loader is unreachable. The bootstrap class loader is always reachable; as a result, system classes may never be unloaded.关于实例的*unreachable*状态,大致可以理解为不能通过特定活动线程对应的栈出发通过引用计算来到达对应的实例,虚拟机协议中对应描述如下:_A reac

8、hable object is any object that can be accessed in any potential continuingcomputation from any live thread._结合上面的虚拟机运行时数据区的介绍|,可以得出结论:类型对应的普通实例、类型对应的java.lang.Class实例、加载此类型的ClassLoader实例,三者中有任何一种或者多种是reachable状态的,那么此类型就不可能被卸载。 4. JMX协议提供了相应的API接口,用来在运行时查询当前虚拟机实例的内存使用和类型加载等信息。这也是很多Java性能监控和分析工具的基础,后

9、面的测试程序中也有相应的代码使用了JMX协议。 测试程序分析【测试程序说明】1. 虚拟机器参数设置如下:-XX: PermSize=4M -XX:MaxPermSize=4M -verbose -verbose:gc设置-verbose参数是为了获取类型加载和卸载的信息设置-verbose:gc是为了获取垃圾收集的相关信息 2. 在D:/classes目录下有一个简单的类型ZhuXing对应的class字节码,测试代码中用URLClassLoader来加载此类型 【测试程序一:模拟PermGen OOM】1try2/准备url3URLurl=newFile(D:/classes).toURL(

10、);4URLurls=url;5678/获取有关类型加载的JMX接口9ClassLoadingMXBeanloadingBean=ManagementFactory.getClassLoadingMXBean();10111213/用于缓存类加载器14ListclassLoaders=newArrayList();1516while(true)17/加载类型并缓存类加载器实例18ClassLoaderclassLoader=newURLClassLoader(urls);19classLoaders.add(classLoader);20classLoader.loadClass(ZhuXin

11、g);2122/显示数量信息(共加载过的类型数目,当前还有效的类型数目,已经被卸载的类型数目)23System.out.println(total:+loadingBean.getTotalLoadedClassCount();24System.out.println(active:+loadingBean.getLoadedClassCount();25System.out.println(unloaded:+loadingBean.getUnloadedClassCount();2627catch(Exceptione)28e.printStackTrace();293031【测试程序一分

12、析】运行测试程序一,输出信息如下(摘取了部分):.Loaded ZhuXing from file:/D:/classes/total: 2914active: 2914unloaded: 0Loaded ZhuXing from file:/D:/classes/total: 2915active: 2915unloaded: 0Full GC 4852K-4852K(8720K), 0.0993780 secsFull GC 4852K-4829K(8720K), 0.0999775 secsFull GC 4829K-4829K(8720K), 0.0989805 secsFull GC

13、 4829K-4829K(8720K), 0.0997261 secs.Exception in thread main java.lang.OutOfMemoryError: PermGen space.Unloading class ZhuXing.Loaded java.lang.Shutdown from D:eos6jdk1.5.0_09jrelibrt.jarLoadedjava.lang.Shutdown$Lockfrom D:eos6jdk1.5.0_09jrelibrt.jar针对以上摘录的虚拟机器运行时信息,分析结论如下:1. 一直在持续的加载类型ZhuXing,而且一直没有卸载,直到PermGen OOM发生。类型ZhuXing无法卸载的原因,前面说明过,是由于对应的类加载器实例一直是reachaable状态,缓存对象实例或者java.lang.Class实例同样可以达到无法卸载类型的效果。 2. 在PermGen OOM发生前,虚拟机进行了非常频繁的垃圾收集,效果甚微 3. 在PermGen OOM发生后,卸载了类型ZhuXing,当前虚拟机实例退出 【测试程序二:PermGen区域垃圾收集】和测试程序一相比,删除了类加载器实例缓存的代码。1try2/准备url3URLurl=newFile

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 大杂烩/其它

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号