java线程多栈会溢出_JVM 内存溢出详解(栈溢出,堆溢出,持久代溢出、无法创建本地线程)...

从运行结果可以看出,JVM进行了一次Minor gc和两次的Major gc,从Major gc的输出可以看出,gc以后old区使用率为134K,而字节数组为10M,加起来大于了old generation(老年代)的空间,所以抛出了异常,如果调整 -Xms21M,-Xmx21M,那么就不会触发gc操作也不会出现异常了。

通过上面的实验其实也从侧面验证了一个结论:对象大于新生代剩余内存的时候,将直接放入老年代,当老年代剩余内存还是无法放下的时候,触发垃圾收集,收集后还是不能放下就会抛出内存溢出异常了。

3.3 持久带溢出(OutOfMemoryError: PermGen space)

我们知道 Hotspot jvm 通过持久带实现了Java虚拟机规范中的方法区,而运行时的常量池就是保存在方法区中。

因此持久带溢出有可能是:

(1) 运行时常量池溢出。

(2)方法区中保存Class对象没有被及时回收掉或者Class信息占用的内存超过了我们配置。

当持久带溢出的时候抛出 java.lang.OutOfMemoryError: PermGen space。可能在如下几种场景下出现:

使用一些应用服务器的热部署的时候,我们就会遇到热部署几次以后发现内存溢出了,这种情况就是因为每次热部署的后,原来的Class没有被卸载掉。

如果应用程序本身比较大,涉及的类库比较多,但是我们分配给持久带的内存(通过-XX:PermSize和-XX:MaxPermSize来设置)比较小的时候也可能出现此种问题。

一些第三方框架,比如spring、hibernate都是通过字节码生成技术(比如CGLib)来实现一些增强的功能,这种情况可能需要更大的方法区来存储动态生成的Class文件。

我们知道Java中字符串常量是放在常量池中的,String.intern()这个方法运行的时候,会检查常量池中是否存和本字符串相等的对象,如果存在直接返回常量池中对象的引用,不存在的话,先把此字符串加入常量池,然后再返回字符串的引用。

那么我们就可以通过String.intern方法来模拟一下运行时常量区的溢出(JDK6下,因为jdk6中常量池位于PremGen区,jdk7之后将常量池移到了Java堆区)。下面我们通过如下的代码来模拟此种情况:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值