1. 栈溢出(StackOverflowError)
  2. 堆溢出(OutOfMemoryError:Java heap space)
  3. 永久代溢出(OutOfMemoryError: PermGen space)
  4. 直接内存溢出

一、堆溢出

创建对象时如果没有可以分配的堆内存,JVM就会抛出OutOfMemoryError:java heap space异常。

堆溢出实例:

/*** VM Args: -Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError*/
public static void main(String[] args) {List<byte[]> list = new ArrayList<>();int i=0;while(true){list.add(new byte[5*1024*1024]);System.out.println("分配次数:"+(++i));}
}运行结果:
分配次数:1
分配次数:2
分配次数:3java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid2464.hprof ...
Heap dump file created [16991068 bytes in 0.047 secs]Exception in thread "main" java.lang.OutOfMemoryError: Java heap spaceat com.ghs.test.OOMTest.main(OOMTest.java:16)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

附:dump文件会在项目的根目录下生成

从上面的例子我们可以看出,在进行第4次内存分配时,发生了内存溢出。

二、栈溢出

栈空间不足时,需要分下面两种情况处理:

  • 线程请求的栈深度大于虚拟机所允许的最大深度,将抛出StackOverflowError
  • 虚拟机在扩展栈深度时无法申请到足够的内存空间,将抛出OutOfMemberError

附:当前大部分的虚拟机栈都是可动态扩展的。

1、栈空间不足——StackOverflowError实例

public class StackSOFTest {int depth = 0;public void sofMethod(){depth ++ ;sofMethod();}public static void main(String[] args) {StackSOFTest test = null;try {test = new StackSOFTest();test.sofMethod();} finally {System.out.println("递归次数:"+test.depth);}}
}执行结果:
递归次数:982
Exception in thread "main" java.lang.StackOverflowErrorat com.ghs.test.StackSOFTest.sofMethod(StackSOFTest.java:8)at com.ghs.test.StackSOFTest.sofMethod(StackSOFTest.java:9)at com.ghs.test.StackSOFTest.sofMethod(StackSOFTest.java:9)
……后续堆栈信息省略
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

我们可以看到,sofMethod()方法递归调用了982次后,出现了StackOverflowError。

2、栈空间不足——OutOfMemberError实例 
单线程情况下,不论是栈帧太大还是虚拟机栈容量太小,都会抛出StackOverflowError,导致单线程情境下模拟栈内存溢出不是很容易,不过通过不断的建立线程倒是可以产生内存溢出异常。

public class StackOOMTest {public static void main(String[] args) {StackOOMTest test = new StackOOMTest();test.oomMethod();}public void oomMethod(){while(true){new Thread(new Runnable() {@Overridepublic void run() {loopMethod();}}).start();;}}private void loopMethod(){while(true){}}
}运行结果:
……操作系统直接挂掉了
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

如果哪位大神能够成功模拟,还望指点一二。

三、永久代溢出

永久代溢出可以分为两种情况,第一种是常量池溢出,第二种是方法区溢出。

1、永久代溢出——常量池溢出 
要模拟常量池溢出,可以使用String对象的intern()方法。如果常量池包含一个此String对象的字符串,就返回代表这个字符串的String对象,否则将String对象包含的字符串添加到常量池中。

public class ConstantPoolOOMTest {/*** VM Args:-XX:PermSize=10m -XX:MaxPermSize=10m* @param args*/public static void main(String[] args) {List<String> list = new ArrayList<>();int i=1;try {while(true){list.add(UUID.randomUUID().toString().intern());i++;}} finally {System.out.println("运行次数:"+i);}}
}运行结果:
……比较尴尬的是,通过intern,始终无法模拟出常量池溢出,我的猜想是JDK7对常量池做了优化。
如果哪位大神成功模拟出来了,还望指点一二。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

找了好久,终于弄清楚了使用string.intern()方法无法模拟常量池溢出的原因。

因为在JDK1.7中,当常量池中没有该字符串时,JDK7的intern()方法的实现不再是在常量池中创建与此String内容相同的字符串,而改为在常量池中记录Java Heap中首次出现的该字符串的引用,并返回该引用。 
简单来说,就是对象实际存储在堆上面,所以,让上面的代码一直执行下去,最终会产生堆内存溢出。 
下面我将堆内存设置为:-Xms5m -Xmx5m,执行上面的代码,运行结果如下:

运行次数:58162
Exception in thread "main" java.lang.OutOfMemoryError: Java heap spaceat java.lang.Long.toUnsignedString(Unknown Source)at java.lang.Long.toHexString(Unknown Source)at java.util.UUID.digits(Unknown Source)at java.util.UUID.toString(Unknown Source)at com.ghs.test.ConstantPoolOOMTest.main(ConstantPoolOOMTest.java:18)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

2、永久代溢出——方法区溢出 
方法区存放Class的相关信息,下面借助CGLib直接操作字节码,生成大量的动态类。

public class MethodAreaOOMTest {public static void main(String[] args) {int i=0;try {while(true){Enhancer enhancer = new Enhancer();enhancer.setSuperclass(OOMObject.class);enhancer.setUseCache(false);enhancer.setCallback(new MethodInterceptor() {@Overridepublic Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {return proxy.invokeSuper(obj, args);}});enhancer.create();i++;}} finally{System.out.println("运行次数:"+i);}}static class OOMObject{}
}运行结果:运行次数:56
Exception in thread "main"
Exception: java.lang.OutOfMemoryError thrown from the UncaughtExceptionHandler in thread "main"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

虽然出现了异常,但是打印的堆栈信息似乎并不是我们想要的……

四、直接内存溢出

DirectMemory可以通过-XX:MaxDirectMemorySize指定,如果不指定,默认与Java堆的最大值(-Xmx指定)一样。 
NIO会使用到直接内存,你可以通过NIO来模拟,在下面的例子中,跳过NIO,直接使用UnSafe来分配直接内存。

public class DirectMemoryOOMTest {/*** VM Args:-Xms20m -Xmx20m -XX:MaxDirectMemorySize=10m* @param args*/public static void main(String[] args) {int i=0;try {Field field = Unsafe.class.getDeclaredFields()[0];field.setAccessible(true);Unsafe unsafe = (Unsafe) field.get(null);while(true){unsafe.allocateMemory(1024*1024);i++;}} catch (Exception e) {e.printStackTrace();}finally {System.out.println("分配次数:"+i);}}
}运行结果:
Exception in thread "main" java.lang.OutOfMemoryErrorat sun.misc.Unsafe.allocateMemory(Native Method)at com.ghs.test.DirectMemoryOOMTest.main(DirectMemoryOOMTest.java:20)
分配次数:27953
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

总结: 
栈内存溢出:程序所要求的栈深度过大。 
堆内存溢出: 分清内存泄露还是 内存容量不足。泄露则看对象如何被 GC Root 引用,不足则通过调大-Xms,-Xmx参数。 
永久代溢出:Class对象未被释放,Class对象占用信息过多,有过多的Class对象。 
直接内存溢出:系统哪些地方会使用直接内存。

代码实现堆溢出、栈溢出、永久代溢出、直接内存溢出相关推荐

  1. java堆结构,以及堆中的永久代

    转自:java堆的结构以及堆中的永久代 java堆不是数据结构意义上的堆(一种有序的树),而是jvm的堆,也即是运行时的数据区.所有类的实例和数组都是在堆上分配内存,它在JVM启动时被创建,对象所占的 ...

  2. 什么是内存溢出?在哪些区域会发生内存溢出?

    什么是内存溢出?在哪些区域会发生内存溢出?回答这个问题,我们需要先看一看Java代码是怎么运行的.现在计入说我们写了一个 HelloWorld.class: 1 2 3 4 5 6 public cl ...

  3. 五种内存溢出案例总结:涵盖栈深度溢出、永久代内存溢出、本地方法栈溢出、JVM栈内存溢出和堆溢出

    大家好,我是冰河~~ 相信小伙伴们在平时工作的过程中,或多或少都会遇到一个场景:内存溢出.如果你没有遇到过这个场景,那就说明你是个假的程序员.哈哈,开个玩笑,平时工作过程中,我们确实会遇到这个问题.今 ...

  4. java 堆中的永久代_JVM中的堆的新生代、老年代、永久代详解

    JVM中的堆一般分为三大部分:新生代.老年代.永久代,其大致的占比如下: 一.新生代 新生代主要用来存放新生的对象.一般占据堆空间的1/3.在新生代中,保存着大量的刚刚创建的对象,但是大部分的对象都是 ...

  5. 马士兵—JVM—内存溢出—1.线上OOM(内存溢出)问题排查——亲测

    1. 模拟线上oom问题 1.1 代码 @GetMapping("/addList")public void addList(){List list = new ArrayList ...

  6. 内存泄露和溢出的区别_Java 中的内存溢出和内存泄露是什么?我给你举个有味道的例子?...

    JAVA中的内存溢出和内存泄露分别是什么,有什么联系和区别,让我们来看一看. 内存泄漏 & 内存溢出 1. 内存泄漏(memory leak ) 申请了内存用完了不释放,比如一共有 1024M ...

  7. ajax timeout 内存溢出,setInterval 和 setTimeout会产生内存溢出

    setInterval 和 setTimeout会产生内存溢出 来一个简单的例子.有兴趣的朋友可以自己尝试 复制代码 代码如下: function a(){ document.title = &quo ...

  8. java模拟内存溢出并分析_本地模拟内存溢出并分析Dump文件

    java Dump文件分析 前言 dump文件是java虚拟机内存在某一时间点的快照文件,一般是.hprof文件,下面自己模拟一下本地内存溢出,生成dump文件,然后通过mat工具分析的过程. 配置虚 ...

  9. java内存溢出怎么排查_java线上内存溢出问题排查步骤

    一般线上遇到比较头疼的就是OOM内存溢出问题,我们都会先看错误日志,如果错误日志能够定位出哪个类对象导致内存溢出,那么我们只需要针对问题修改bug就好.但是很多时候我们单凭日志无法定位出内存溢出问题, ...

  10. linux weblogic 内存溢出,weblogic 安装升级补丁出现内存溢出问题解决

    执行weblogic升级命令时,出现内存溢出问题: d:\Oracle\Middleware\utils\bsu>bsu.cmd -install -patch_download_dir=d:\ ...

最新文章

  1. c语言循环控制答案,C语言程序设计 实四 循环控制 答案 《西北民大 电气院》.doc...
  2. 模块化、层次化网络监控平台
  3. for(;;)函数中判断条件执行顺序
  4. mysql执行过程五步_简单五步教你搭建MySQL主从复制
  5. GARFIELD@01-19-2005
  6. java jdk 未知错误_解决JAVA JDK安装出错的最常见问题,帮你排除困扰
  7. python开发学习记录
  8. 设置Myeclipse中的代码格式化、及保存时自动格式化
  9. swift UI专项训练15 PcikerView老虎机视图
  10. 设置和开通freebsd远程登录
  11. php基本语法(简略篇)
  12. 2040: [蓝桥杯2022初赛] 砍竹子(优先队列)
  13. git分支的拉取和获取master分支最新代码
  14. Java录制网页_Java 录制语音的实现代码
  15. 服务网格领域的百花齐放
  16. python 文字识别 准确率_关于OCR图片文本检测、推荐一个 基于深度学习的Python 库!...
  17. 中国微商概念及产业链分析
  18. 如何彻底删除ELTIMA的vspd(虚拟串口)
  19. python水浒传名字次数_可视化分析《水浒传》各章回人名
  20. 网上报修 php源码,25175网上报修系统管理平台 v2.9

热门文章

  1. Codeforces_714_A
  2. 如何在OpenWRT的非交换网卡/单口网卡(OpenWRT x86)下配置802.1Q VLAN
  3. [渝粤教育] 西南科技大学 民法学 在线考试复习资料
  4. ArcGIS Engine开发教程之图层符号化
  5. VirtuoZo:航摄影像的处理及拼接
  6. 教你10分钟电脑配置挑选装机速成攻略
  7. 商用字体网站,再也不用怕侵权
  8. Python数据分析(五) —— 绘制直方图
  9. 《计算机文件管理》教学设计,《文件和文件夹的操作》教学设计
  10. Skyline三维地理信息系统软件平台