实战:OutOfMemoryError异常

上一篇讲了jvm内存模型,还不了解的小伙伴可以翻看一下,链接如下:https://blog.csdn.net/cyberHerman/article/details/94045291

这篇就根据jvm内存模型里面的每一块来测试一下OOM异常。

说明,一下测试都是基于 Sun公司的HotSpot虚拟机运行的。

java堆溢出

上篇已经介绍java堆用于存储对象实例,要想堆溢出,只要不断的创建对象,并且保证 GC root到对象之间有可达路径来避免对象被回收  (jvm是通过可达算法来判断对象是否存活,从GC root作为起点向下搜索,当一个对象 到 GC root没有任何引用连的时候,则证明此对象是不可用的,被判定为可回收对象,但是对象一定死了吗?答案是否定的,对象是会自我拯救的。关于gc,我想我后面可能会抽时间写出来,毕竟挺interesting 是吧 ^_^)    ,那么对象数量达到最大堆容量就会内存溢出。

首先设置 java堆大小为10MB,不可扩展(将堆最小值 -Xms与最大值-Xmx设置为一样就可以避免堆自动扩展。)

eclipse中 在 window--> preferences-->java-->installed jres 点击你的jdk  edit  输入 

好了 测试开始 。

public class Test {
	static class OOMObject{
	}
	public static void main(String[] args) {
		List<OOMObject> list = new ArrayList<OOMObject>();
		while (true) {
			list.add(new OOMObject());
		}
	}
	
}

可以看到结果如下图:

算了不贴代码了,直接贴图。至于oom溢出的解决办法就要通过工具对症下药,查找泄露对象到gc root的相关联,看看为什么没有被回收。或者想办法扩充堆内存。

虚拟机栈和本地方法栈溢出

这块区域存在两种异常情况:

1. 如果线程请求的栈深度大于虚拟机允许的深度,抛出StackOverflowError异常;

2. 如果虚拟机栈可以动态扩展,且扩展时无法申请到足够的内存时会抛出OutOfMemoryError异常。看代码吧。

这里把异常分为两种,当栈无法继续分配时,到底是内存太小,还是已用的栈太大,其实都是一样。

我先在单线程下通过下面两种方法均无法产生OOM,都只产生了StackOverflowError,两种方法如下:

1、使用-Xss参数减小栈内存容量。

2、定义大量本地变量,增大此方法栈中本地变量表长度。

测试代码如下:

可以看出,单线程下 无论是由于栈太大还是虚拟机太小,只要内存无法分配,只会抛出StackOverflowError异常。

下来再多线程下测试。(重要提示 测试此方法前,请保存当前工作,会死机,你懂得,代码我提供出来 就不发测试结果的图了,此前为了测试已经关机两次。。。。)

方法区和运行时常量池溢出

方法区包含运行时常量池,所以一起测试,我只要将运行时常量池塞满就可以。运行时常量池可以通过String.intern()方法测试,此方法这里不做介绍。

当前许多主流框架,spring hibernate 在进行类增强时候,都会用到GCLib字节码技术。增强的类越多,就需要越大的方法区来保证动态生成的类可以加载到内存。

最后本地内存直接看图

溜了溜了。休息.谢谢!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值