参考:深入理解java虚拟机一书

开始之前,我们也应当搞清楚连个概念,内存泄漏Memory Leak 内存溢出:

内存泄漏:程序中间动态分配了内存,但是在程序结束时没有释放内存,造成这部分内存不可用。与硬件无关

而内存溢出就是我们接下来要讨论的;

这篇文章的目的主要有两个:

第一:验证Java虚拟机中各个运行区域存储的内容

第二:在遇到内存溢出时能快速的根据异常信息判断是哪个区域的内存溢出

1.java堆:java堆用于存储对象实例,对象数量达到最大堆溢出

2.虚拟机栈和本地方法栈:虚拟机栈主要存放对象的引用,基本数据类型等。 本地方法栈为虚拟机使用到的Native方法服务

虚拟机栈描述的是java方法执行的内存模型:每个方法被执行时都会同时创建一个栈帧,用于存储局部变量表、操作栈、动态链接、方法出口等信息。每一个方法被调用直至执行完成,就对应着一个栈帧在虚拟机中从入栈到出栈的过程

3.运行时常量池:主要存放编译生成的各种字面量和符号引用,向运行时常量池中添加内容,到达最大抛出异常

4.方法区溢出:用于存放Class的相关信息,如:类名、访问修饰符、常量池、字段描述、方法描述等,GC区域也属于方法区

5.本机直接内存溢出:直接内存不是虚拟机运行时数据区的一部分,也不是Java虚拟机规范中定义的内存区域,但是其引用频繁,也可能导致内存溢出;

PS:下边代码注释中的JVM属性是对虚拟机的设置,

堆溢出:HeapOOM

/**
* 异常类型:堆内存溢出
* JVM:-Xms20M -Xmx20M -XX:+HeapDumpOnOutOfMemoryError
* *-Xms堆的最小值参数 -Xmx堆的最大值参数 设置为一样即可避免自动扩展
* 测试思路:不断地创建对象,使其填满堆 ,对象存放于java堆中
* java堆用于存储对象实例,对象数量达到最大堆溢出
* @author TH
*PS:区分 内存泄漏 Memory Leak和内存溢出Memory Overflow
*/
public class HeapOOM {
static class OOMObject{ }
public static void main(String[] args) {
List<OOMObject> list = new ArrayList<OOMObject>(); while(true){
list.add(new OOMObject());
}
}
}

虚拟栈溢出JavaVMStackSOF

**
* 异常类型:虚拟机栈溢出
* JVM:-Xss128k 减少栈内存容量
* **如果线程请求的栈深度大于虚拟机所允许的最大深度将抛出StackOverflowError异常
* **如果虚拟机在扩展栈时无法申请到足够的内存空间,则抛出OutOfMemoryError异常
* 通常在建立多线程过多的情况下会发生栈溢出
* 减少最大堆和减少栈容量可以换取更多的线程
* @author TH
*
*/
public class JavaVMStackSOF {
private int stackLength = 1; public void stackLeak(){
stackLength++;
stackLeak();
} public static void main(String[] args) throws Throwable{
JavaVMStackSOF oom = new JavaVMStackSOF();
try{
oom.stackLeak();
}catch(Throwable e){
System.out.println("stack length:"+oom.stackLength);
throw e;
}
}
}

运行时常量池溢出RuntimeConstantPoolOOM

/**
* 异常类型:运行时常量池溢出
* JVM:-XX:PermSize=10M -XX:MaxPermSize=10M 限制方法区的大小
* 测试思路:运行时常量池主要存放编译生成的各种字面量和符号引用,向运行时常量池中添加内容,到达最大抛出异常
* 使用String.intern这个Native方法
* 运行时常量池属于方法区
* @author TH
*
*/
public class RuntimeConstantPoolOOM {
public static void main(String[] args) {
//使用List保持常量池的引用,避免Full GC回收常量池行为
List<String> list = new ArrayList<String>();
//10M的PerSize在Integer的范围内足够产生OOM
int i=0;
while(true){
list.add(String.valueOf(i++).intern());
}
}
}

方法区溢出JavaMethodAreaOOM

public class JavaMethodAreaOOM {
/**
* 异常类型:方法区溢出
* JVM:-XX:PermSize=10M -XX:MaxPermSize=10M
* 方法区作用:用于存放Class的相关信息,如:类名、访问修饰符、常量池、字段描述、方法描述等,GC区域也属于方法区
* 测试思路:运行大量的类去填满方法区,直到溢出
*
* 类越多,就需要越大的方法区来保证动态生成的Class可以加载到内存
* 实现:借助CGLib生成
* @param args
*/
public static void main(String[] args) {
while(true){
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(OOMObject.class);
enhancer.setUseCache(false);
enhancer.setCallback(new MethodInterceptor() {
/**
* obj为由CGLib动态生成的代理类实例,
* method 为实体类所调用的被代理的方法的引用
* Object[] args为参数值列表
* proxy为生成的代理类对方法的代理引用
*/
@Override
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
return proxy.invokeSuper(obj, args);
}
});
enhancer.create();
}
}
static class OOMObject{ }
}

本机直接内存溢出DirectMemoryOOM

/**
* VM:-Xmx20M -XX:MaxDirectMemorySize=10M 指定DirectMemory容量
* 本机直接内存溢出
* @author TH
*
*/
public class DirectMemoryOOM {
private static final int _1MB = 1024 * 1024;
public static void main(String[] args) {
Field unsafeField = Unsafe.class.getDeclaredFields()[0];
unsafeField.setAccessible(true);
Unsafe unsafe = unsafeField.get(null);
while(true){
unsafe.allocateMemory(_1MB);
}
}
}

Java虚拟机学习总结之OutOfMemoryError异常的更多相关文章

  1. 《深入Java虚拟机学习笔记》- 第17章 异常

    <深入Java虚拟机学习笔记>- 第17章 异常

  2. java虚拟机学习-JVM内存管理:深入Java内存区域与OOM(3)

    概述 Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外面的人想进去,墙里面的人却想出来. 对于从事C.C++程序开发的开发人员来说,在内存管理领域,他们即是拥有最高权力的皇帝又 ...

  3. java虚拟机学习-触摸java常量池(13-1)

    java虚拟机学习-深入理解JVM(1) java虚拟机学习-慢慢琢磨JVM(2) java虚拟机学习-慢慢琢磨JVM(2-1)ClassLoader的工作机制 java虚拟机学习-JVM内存管理:深 ...

  4. java虚拟机学习-JVM内存管理:深入垃圾收集器与内存分配策略(4)

    Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外面的人想进去,墙里面的人却想出来. 概述: 说起垃圾收集(Garbage Collection,下文简称GC),大部分人都把这项 ...

  5. 《深入Java虚拟机学习笔记》- 第19章 方法的调用与返回

    <深入Java虚拟机学习笔记>- 第19章 方法的调用与返回

  6. 《深入Java虚拟机学习笔记》- 第16章 控制流

    <深入Java虚拟机学习笔记>- 第16章 控制流

  7. 《深入Java虚拟机学习笔记》- 第13章 逻辑运算

    <深入Java虚拟机学习笔记>- 第13章 浮点运算

  8. 《深入Java虚拟机学习笔记》- 第14章 浮点运算

    <深入Java虚拟机学习笔记>- 第13章 浮点运算

  9. 《深入Java虚拟机学习笔记》- 第8章 连接模型

    Java虚拟机学习笔记(八)连接模型

随机推荐

  1. 洛谷 P1930 亚瑟王的宫殿 Camelot

    传送门 题目大意:棋盘有骑士有王,让所有点跳到一个点,求所有棋子跳的步数和,和最小. 题解:bfs+枚举 王的人生: 1):自己走到聚集点 2):某个骑士来到王这里,两个棋子一起到聚集点 3):王走几 ...

  2. retful上传文件php的实现

    项目中要使用restful上传文件到服务器,一直不能成功,后生成相关串后在postman中上传成功,利用这个工具生成php curl的代码,后逐步比对产生以下代码. /**     * 上传文件    ...

  3. 提升Apache网站访问速度的优化方法

    Apache是世界使用排名第一的Web服务器软件.它可以运行在几乎所有广泛使用的计算机平台上,由于其跨平台和安全性被广泛使用,是最流行的Web服务器端软件之一. 在Apache服务器上怎样优化才能提高 ...

  4. Tomcat服务器下 catalina.out 日志开关

    很多异常在 debug 日志里不会打印,但在 catalina.out 里会打印,比如方法调用找不到,jdk 版本不匹配等.但是打开了该日志开关又会产生一个问题,就是它会哗啦啦的不断急剧膨胀,文件太大 ...

  5. C++的三大特性?C也可以做到

    C++的三大特性是什么?封装.继承与多态,那么今天这篇文章小编就来介绍一下,如何用C语言实现C++的这三个特性. 1.封装 何为封装? 在面向对象的思想中,将数据和对数据的操作封装在一起——即类. 类 ...

  6. 普及组2008NOIP 排座椅(贪心+排序)

    排座椅 时间限制: 1 Sec  内存限制: 50 MB提交: 4  解决: 3[提交][状态][讨论版][命题人:外部导入] 题目描述 上课的时候总有一些同学和前后左右的人交头接耳,这是令小学班主任 ...

  7. 技术流:6大类37种方式教你在国内推广App

    转自:http://www.gamelook.com.cn/2015/01/201906 如何有效的推广自己App,是每个发行商都要考虑的问题,当然每个产品都有适合自己的推广方式.本文就集结了包括应用 ...

  8. MFC学习(五)常见面试题

    1:应用程序类 CTestOneApp::InitInstance 可以看做是MFC程序的入口函数,main函数隐藏在这个函数中.实际开发中一般不需要对这个类进行操作,但如果要在建立主对话框之前处理一 ...

  9. DOM对象与JQuery对象

    在初学JAVA时,经常会迷惑,分不清DOM/JQuery对象,以及可以调用的方法. 1.什么是DOM/JQuery对象 DOM对象,即是我们用传统的方法(javascript)获得的对象: eg:va ...

  10. 关于Oracle to_char()函数中的IW,WW 周别显示

    1)ww的算法为每年1月1日为第一周开始,date+6为每一周结尾 例如20050101为第一周的第一天,而第一周的最后一天为20050101+6=20050107 公式 每周第一天 :date + ...