写代码实现堆溢出、栈溢出、永久代溢出、直接内存溢出
来源:互联网 发布:淘宝司法拍卖商铺税费 编辑:程序博客网 时间:2024/06/05 18:00
- 栈溢出(StackOverflowError)
- 堆溢出(OutOfMemoryError:Java heap space)
- 永久代溢出(OutOfMemoryError: PermGen space)
- 直接内存溢出
一、堆溢出
创建对象时如果没有可以分配的堆内存,JVM就会抛出OutOfMemoryError:java heap space异常。
堆溢出实例:
- 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实例
- 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,导致单线程情境下模拟栈内存溢出不是很容易,不过通过不断的建立线程倒是可以产生内存溢出异常。
- 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对象包含的字符串添加到常量池中。
- 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,执行上面的代码,运行结果如下:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
2、永久代溢出——方法区溢出
方法区存放Class的相关信息,下面借助CGLib直接操作字节码,生成大量的动态类。
- 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来分配直接内存。
- 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对象。
直接内存溢出:系统哪些地方会使用直接内存。
最后,送大家一句话:觉知此事要躬行。
很多时候,我们看别人提供的示例,都觉得蛮合理,但是实际运行起来,有可能并非如此。
- 写代码实现堆溢出、栈溢出、永久代溢出、直接内存溢出
- 写代码实现堆溢出、栈溢出、永久代溢出、直接内存溢出
- 堆溢出,栈溢出
- 堆溢出、栈溢出
- 写Java代码分别使堆溢出,栈溢出
- 写Java代码分别使堆溢出,栈溢出
- 写Java代码分别使堆溢出,栈溢出
- 在JDK1.6下,模仿堆、栈、永久代溢出
- 代码实现内存溢出
- Java JVM:内存溢出(栈溢出,堆溢出,持久代溢出以及 nable to create native thread)
- Java JVM:内存溢出(栈溢出,堆溢出,持久代溢出以及 nable to create native thread),
- Java JVM:内存溢出(栈溢出,堆溢出,持久代溢出以及 nable to create native thread)
- Java JVM:内存溢出(栈溢出,堆溢出,持久代溢出以及 nable to create native thread)
- java内存溢出示例(堆溢出、栈溢出)
- java内存溢出示例(堆溢出、栈溢出)
- java内存溢出示例(堆溢出、栈溢出)
- java代码实现JVM栈溢出,堆溢出
- 堆溢出和栈溢出
- [noip 2017]普及组 T4
- 类成员函数参数为该类某个静态成员函数指针,需要在静态函数内使用当前实例的非静态数据成员
- Spring Boot应用连接数据库MySQL,并编写自定义SQL
- Docker命令小记。
- opencv提取截获图像,任意区域
- 写代码实现堆溢出、栈溢出、永久代溢出、直接内存溢出
- 通过导数求极值
- 数据库查询语言(2)DQL——零散知识
- 升级到12c时遇到的问题
- Selenium IDE 常用命令
- ssm整合步骤
- git 本地删除文件后,git status会显示红色的那个文件。
- 本地IIS部署Web项目
- [JAVA]集合框架之自己实现一个具有基本增查删改功能的ArrayList