JVM异常之:堆溢出OutofMemoryError
1、堆溢出
Java 堆内存的OutOfMemoryError异常是实际应用中最常见的内存溢出异常情况。出现Java 堆内存溢出时,异常堆栈信息“java.lang.OutOfMemoryError”会跟着进一步提示“Java heap space”。
要解决这个区域的异常,一般的手段是首先通过内存映像分析工具(如Eclipse Memory Analyzer)对dump 出来的堆转储快照进行分析,重点是确认内存中的对象是否是必要的,也就是要先分清楚到底是出现了内存泄漏(Memory Leak)还是内存溢出(Memory Overflow)。使用Eclipse Memory Analyzer 打开的堆转储快照文件。
如果是内存泄漏,可进一步通过工具查看泄漏对象到GC Roots 的引用链。于是就能找到泄漏对象是通过怎样的路径与GC Roots 相关联并导致垃圾收集器无法自动回收它们的。掌握了泄漏对象的类型信息,以及GC Roots 引用链的信息,就可以比较准确地定位出泄漏代码的位置。
如果不存在泄漏,换句话说就是内存中的对象确实都还必须存活着,那就应当检查虚拟机的堆参数(-Xmx 与-Xms),与机器物理内存对比看是否还可以调大,从代码上检查是否存在某些对象生命周期过长、持有状态时间过长的情况,尝试减少程序运行期的内存消耗。
以上是处理Java 堆内存问题的简略思路,处理这些问题所需要的知识、工具与经验在后面的几次分享中我会做一些额外的分析。
示例:
package com.dxz.jvm; import java.util.ArrayList;
import java.util.List; /**
* @Described:堆溢出测试
* @VM args:-verbose:gc -Xms20M -Xmx20M -XX:+PrintGCDetails
*/
public class HeapOutOfMemory { public static void main(String[] args) {
List<TestObject> cases = new ArrayList<TestObject>();
HeapOutOfMemory heapOutOfMemory = new HeapOutOfMemory();
while (true) {
cases.add(heapOutOfMemory.new TestObject()); }
} public class TestObject {
private double a = 34.53;
private Integer b = 9999999;
}
}
结果:
2、常量池溢出(常量池都有哪些信息,我们在后续的JVM类文件结构中详细描述)
2.1、方法区溢出(Perm持久代溢出)
在jdk1.6及之前的版本中,常量池放在Perm区也即是方法区中,所以在jdk1.6版本中,常量池溢出可以说是方法区溢出。
方法区溢出的示例见《JVM体系结构之七:持久代、元空间(Metaspace) Metaspace 之三--了解String类的intern()方法、常量池介绍、常量池从Perm-->Heap》
在网络上看到一个cglib导致的方法区溢出的示例:
package com.dxz.jvm; import java.lang.reflect.Method; import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy; /**
* @VM args : -XX:PermSize=10M -XX:MaxPermSize=10M
*/
public class MethodAreaOutOfMemory { public static void main(String[] args) {
while (true) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(MethodAreaOutOfMemory.TestObject.class);
enhancer.setUseCache(false);
enhancer.setCallback(new MethodInterceptor() {
public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable {
return arg3.invokeSuper(arg0, arg2);
}
});
enhancer.create();
}
} public static class TestObject {
private double a = 34.53;
private Integer b = 9999999;
}
}
运行结果:
- Caused by: java.lang.OutOfMemoryError: PermGen space
- at java.lang.ClassLoader.defineClass1(Native Method)
- at java.lang.ClassLoader.defineClassCond(ClassLoader.java:632)
- at java.lang.ClassLoader.defineClass(ClassLoader.java:616)
- ... 8 more
方法区溢出也是一种常见的内存溢出异常,一个类要被垃圾收集器回收掉,判定条件是比较苛刻的。在经常动态生成大量Class的应用中,需要特别注意类的回收状况。这类场景除了上面提到的程序使用了CGLib字节码增强和动态语言之外,常见的还有:大量JSP或动态产生JSP文件的应用(JSP第一次运行时需要编译为Java类)、基于OSGi的应用(即使是同一个类文件,被不同的加载器加载也会视为不同的类)等。
2.2、常量池导致的堆溢出
在jdk1.7以后,perm持久代已经被移除,常量池也放到了堆中,其导致的溢出也变成了堆溢出。
示例见《JVM体系结构之七:持久代、元空间(Metaspace) Metaspace 之三--了解String类的intern()方法、常量池介绍、常量池从Perm-->Heap》
JVM异常之:堆溢出OutofMemoryError的更多相关文章
- java代码实现JVM栈溢出,堆溢出
参考博客:http://www.cnblogs.com/tv151579/p/3647238.html 背景知识: 栈存放什么:栈存储运行时声明的变量——对象引用(或基础类型, primitive)内 ...
- OutOfMemoryError异常——Java堆溢出。
https://blog.csdn.net/en_joker/article/details/79726975 (将堆的最小值-Xms参数与最大值-Xmx参数设置为一样即可避免堆自动扩展),通过参数- ...
- Java JVM:内存溢出(栈溢出,堆溢出,持久代溢出以及 nable to create native thread)
转载自https://github.com/pzxwhc/MineKnowContainer/issues/25 包括:1. 栈溢出(StackOverflowError)2. 堆溢出(OutOfMe ...
- JVM 内存溢出详解(栈溢出,堆溢出,持久代溢出、无法创建本地线程)
出处: http://www.jianshu.com/p/cd705f88cf2a 1.内存溢出和内存泄漏的区别 内存溢出 (Out Of Memory):是指程序在申请内存时,没有足够的内存空间供 ...
- JVM探秘2--详解内存溢出OutOfMemoryError异常
JVM运行时内存被划分成多个区域,而除了程序计数器之外,其他几个区都会出现OutOfMemoryError异常,主要原因就是对应内存区域的内存不足以再分配内存,一般要么是内存泄漏了要么就是内存参数设置 ...
- JVM异常之:方法区溢出OutOfMemoryError: PermGen space
1.方法区溢出(Perm持久代溢出) 在jdk1.6及之前的版本中,常量池放在Perm区也即是方法区中,所以在jdk1.6版本中,常量池溢出可以说是方法区溢出. 示例一: 方法区溢出的示例见<J ...
- JVM的参数设置与OutOfMemoryError异常关系
Java堆中存放Object对象数据,例如new出来的Object.当没有任何引用指向某对象时,该对象可能被垃圾回收.有关垃圾回收算法,可参考其他有关文章,网上很多.关于对象引用,按强弱还有强引用,软 ...
- JVM--你常见的jvm 异常有哪些? 代码演示:StackOverflowError , utOfMemoryError: Java heap space , OutOfMemoryError: GC overhead limit exceeded, Direct buffer memory, Unable_to_create_new_native_Thread, Metaspace
直接上代码: public class Test001 { public static void main(String[] args) { //java.lang.StackOverflowErro ...
- JVM(2) Java内存溢出异常
在Java虚拟机运行时数据区中,除了程序计数器之外,虚拟机栈.本地方法栈.方法区和Java堆都有发生OutOfMemoryError(简称OOM)异常的可能. 一.Java堆溢出 Java堆用于存储对 ...
随机推荐
- Damped Track 阻尼跟随
Damped Track 阻尼跟随 https://www.youtube.com/watch?v=pd1od5WPCUw 2个网格及对应的2个空对象Z轴方向网格:{O.up}; 上方园孔把手中间放空 ...
- 铁三测试题——权限、你是管理员吗?——WP
权限 [题目描述]:你是管理员吗? [解题链接]:http://ctf4.shiyanbar.com/web/root/index.php 首先看题,提到“权限”,“管理员”,这就是说涉及到管理员的账 ...
- 从简单的mongodb example 的观察
https://github.com/no7dw/mongodb-example 这是最基础的连接查询.(branch master) var MongoClient = require('mongo ...
- AssemblyVersion和AssemblyFileVersion的区别
简而言之,AssemblyVersion: 是程序集的版本,.NET的CLR用,用于标识出该dll的版本信息,用于定义强名称的版本号: AssemblyFileVersion: 为编译器生成的文件加入 ...
- KiCad 如何画板框
KiCad 如何画板框 一块 PCB 最开始就是画板框. 设置工作到 Edge.Cuts 点菜单放置 -> 线(L) 板框画好.
- CloudStack学习-3
此次试验主要是CloudStack结合openvswitch 背景介绍 之所以引入openswitch,是因为如果按照之前的方式,一个网桥占用一个vlan,假如一个zone有20个vlan,那么岂不是 ...
- MySQL 数据类型对比:char 与 varchar;varchar 与 text;datetime 与 timestamp;blob 与 text;
char 与 varchar char(n) 若存入字符数小于n,则以空格补于其后,查询之时再将空格去掉.所以 char 类型存储的字符串末尾不能有空格,varchar 不限于此. char(n) 固 ...
- TypeScript 之 函数
https://m.runoob.com/manual/gitbook/TypeScript/_book/doc/handbook/Functions.html 为函数定义类型 为函数添加类型: fu ...
- golang channel几点总结
golang提倡使用通讯来共享数据,而不是通过共享数据来通讯.channel就是golang这种方式的体现. Channel 在golang中有两种channel:带缓存的和不带缓存. 带缓存的cha ...
- Myeclipse 配置Git详解
Myeclipse+Git EGit安装 MyEclipse已经集成了Git插件EGit,在window->Preference里搜索git可以看到. 如果没有,安装方式为Help-> ...