OOM(Out Of Menmory Error)
JAVA虚拟机中 除程序计数器意外 虚拟机的内存其他几个运行时区域都有发生OOM的可能Java 堆溢出
GC Roots 到对象之间有可达路径来避免垃圾回收机智清理这些对象 就会在对象数量达到最大堆的绒容量 然后产生内存溢出异常Eclipse 的 Debug 页面中设置虚拟机参数
代码:
-verbose:gc -Xms20M -Xmx20M Xmn10M -XX:+PrintGCDaetails -XX:SurvivorRatio=8
JAVA堆的大小设置最小值 -Xms
JAVA堆的大小设置最大值 -Xmx
解决异常
首先通过内存映射分析工具 如 Eclipse Memory Analyzer 堆 dump出的异常堆转储进行快照解析确认内存中的对象是否是必要的 也就是先分清楚是 内存泄漏 Memory Leak 还是Memory Overflow 如果是内存泄漏 可通过工具进一步查看泄露的对象到GC Roots的引用链 就能找到泄露对象是怎么通过路径与 GC Roots 相关联导致垃圾收集器无法回收他们如果不存在泄露 就检查堆参数 -Xmx 与 -Xms 与机器物理内存对比是否还可以调大 从代码上检测 是否是某些对象的生命周期过长持有状态时间过长 尝试减少代码运行期间的内存消耗虚拟机栈 和 本地方法栈 溢出
HotSpot 虚拟机不区分 虚拟机栈 和 本地方法栈 因此Xoss(设置本地方法栈内存大小)参数虽然存在但是是无效的虚拟机栈 和 本地方法栈两种异常:
线程请求栈的深度大于虚拟机允许的最大深度 抛出 StackOverflowError
如果虚拟机在扩展栈是无法申请到足够的内存空间 抛出 Out Of Menmory Error
注:单个线程下 无论是栈帧太大还是虚拟机栈容量太小当内存无法分配的时候抛出的都是StackOverflowError运行时常量池溢出
如果向运行时常亮去添加内容最简单的做法就是使用 String.intern() 这个 Narive 方法 该方法作用是如果池中包含一个等于此String对象的字符串 则返回代表池中这个字符串的 String 对象 否则将该 String 对象 的字符串添加到常量池中并返回此 String 对象的引用-XX:PermSize 方法区最小 -XX:MaxPermSize 方法区最大值如果运行时常量池 OOM 提示信息为 OutOfMemoryError : PermGen space 表示运行时常量池属于方法区的一部分方法区溢出
方法区是用于存放 Class信息的 如类名 访问修饰符 常量池 等当前主流AOP框架 (Spring Hibernate 等) 都会使用到 CFLib 这类字节码技术对类进行加强 增强的类越多 就越需要越大的方法区来保证 动态生成的Class 可以载入内存在动态生成大量 Class 的应用中 需要特别注意类的回收状况 注:除了使用GCLib字节码增强意外 常见的还有 JSP 或者动态产生JSP的应用文件(JSP在第一次运行时要编译为JAVA类)或是基于 OSGi(注: OSGi(Open Service Gateway Initiative)技术是Java动态化模块化系统的一系列规范。OSGi一方面指维护OSGi规范的OSGI官方联盟,另一方面指的是该组织维护的基于Java语言的服务(业务)规范。简单来说,OSGi可以认为是Java平台的模块层。) 的应用即使是同一个类呗不同的加载器加载也会视为不同的类