1、Java堆溢出 (OOM)

Java堆用于存储对象的实例,只要不断地创建对象,并且保证GC roots到对象之间有可达路径来避免垃圾回收机制清除这些对象,那么在对象数量到达最大堆的容量限制后就会产生内存溢出异常。如下所示,

public class Test {

public static void main(String[] args){

List list=new ArrayList();   //持有“大对象”的引用,防止垃圾回收

while(true){

int[] tmp = new int[10000000];  //不断创建“大对象”

list.add(tmp);

}

}

}

要解决这个异常,一般先通过内存映像分析工具对堆转储快照分析,确定内存的对象是否是必要的,即判断是内存泄露还是内存溢出。如果是内存泄露,可以进一步通过工具查看泄露对象到GC Roots的引用链,比较准确地定位出泄露代码的位置。如果是内存溢出,可以调大虚拟机堆参数,或者从代码上检查是否存在某些对象生命周期过长的情况。

2、虚拟机栈和本地方法栈溢出 (SOF/OOM)

(1). SOF

如果线程请求的栈深度大于虚拟机栈允许的最大深度,将抛出StackOverflowError异常。我们知道,每当Java程序启动一个新的线程时,Java虚拟机会为它分配一个栈,并且Java虚拟机栈以栈帧为单位保持线程运行状态。每当线程调用一个方法时,JVM就压入一个新的栈帧到这个线程的栈中,只要这个方法还没返回,这个栈帧就存在。 那么可以想象,如果方法的嵌套调用层次太多,比如递归调用,随着Java虚拟机栈中的栈帧的不断增多,最终很可能会导致这个线程的栈中的所有栈帧的大小的总和大于-Xss设置的值,从而产生StackOverflowError溢出异常。看下面的栗子:

public class Test {

public static void main(String[] args) {

method();

}

//递归调用导致 StackOverflowError

public static void method(){

method();

}

}

上面的SOF异常就是由递归引起的,具体而言就是因为method()方法中没有递归终止条件,从而使得该方法不断递归调用、不断创建栈帧导致的。

(2). OOM

如果虚拟机在拓展栈时无法申请到足够的内存空间,则抛出OutOfMemoryError异常。在虚拟机栈和本地方法栈发生OOM异常场景如下:当Java 程序启动一个新线程时,若没有足够的空间为该线程分配Java栈(一个线程Java栈的大小由-Xss设置决定),JVM将抛出OutOfMemoryError异常。

3、方法区和运行时常量池溢出 (OOM)

运行时常量池溢出的情况:String.intern()是一个native方法,在JDK1.6及之前的版本中,它的作用是:如果字符串常量池中已经包含一个等于此String对象的字符串,则返回代表池中这个字符串的String对象,否则将此String对象包含的字符串添加到常量池中,并且返回此String对象的引用。由于常量池分配在永久代中,如果不断地使用intern方法手动入池字符串,则会抛出OutOfMemoryError异常。但在JDK1.7及其以后的版本中,对intern()方法的实现作了进一步改进,其不会再复制实例到常量池中,而仅仅是在常量池中记录首次出现的实例的引用。看下面的例子(在JDK1.7中运行),

public class Test {

public static void main(String[] args) {

String str1 = new StringBuilder("计算机").append("软件").toString();

System.out.println(str1.intern() == str1);

String str2 = new StringBuilder("java").toString();

System.out.println(str2.intern() == str2);

}/* Output:

true

false

*///:~

为什么第一个返回true,而第二个返回false呢?因为在JDK1.7中,intern()方法的实现不会再复制实例,只是在常量池中记录 首次 出现的实例的引用,因此str1.intern()和str1指向的是同一个字符串,所以返回true。同一个引用。对于“java”这个字符串,由于在执行StringBuilder.toString() 之前已经出现过,所以字符串常量池中在new StringBuilder(“java”).toString()之前已经有它的引用了,不符合首次出现的原则,因此返回fasle。有人可能心里可能就要嘀咕了,为啥第二个不符合首次出现的原则,而第一个就符合首次出现的原则呢? 实际上,

String str2 = new StringBuilder("java").toString();

1

等价于:

String s1 = "java";

StringBuilder sb = new StringBuilder(s1);

String str2 = sb.toString();

// StringBuilder的 toString()方法

public String toString() {

// Create a copy, don't share the array

return new String(value, 0, count);

}

由上面代码可知,字符串”java”早就出现了,因此不符合首次出现的原则,返回false。同理,“计算机软件”这个字符串在new StringBuilder(“计算机”).append(“软件”).toString()之前从未出现过,因此符合首次出现的原则,返回true。

方法区溢出的情况:一个类要被垃圾回收器回收掉,判断条件是比较苛刻的。在经常动态产生大量Class的应用中,需要特别注意类的回收状况,比如动态语言、大量JSP或者动态产生JSP文件的应用(JSP第一次运行时需要编译为Java类)、基于OSGi的应用(即使是同一个类文件,被不同的加载器加载也会视为不同的类)等。

java 堆栈内存例子,内存溢出OOM和堆栈溢出SOF的示例相关推荐

  1. java log4配置例子,log4j.properties配置属性详解与配置示例

    log4j.properties配置属性详解与配置示例 发布时间:2018-03-27作者:laosun阅读(1535) log4j.properties配置属性详解与配置示例,拿走直接用!详细解答了 ...

  2. Java内存溢出(OOM)异常完全指南

    原文:http://luecsc.blog.51cto.com/2219432/1948800 这也许是目前最为完整的Java OOM异常的解决指南. 1.Java.lang.OutOfMemoryE ...

  3. Java常见内存溢出(OOM)解决方案

    Java 常见内存溢出(OOM)解决方案 一,jvm内存区域   1,         程序计数器 一块很小的内存空间,作用是当前线程所执行的字节码的行号指示器. 2,         java栈 与 ...

  4. Java内存溢出(OOM)分析

    当JVM内存不足时,会抛出java.lang.OutOfMemoryError. 主要的OOM类型右: Java heap space:堆空间不足 GC overhead limit exceeded ...

  5. Java内存溢出OOM之dump分析

    目录 内存泄露 内存溢出 1.Java堆内存异常 报错方式 原因 2.Java栈内存异常 报错方式 原因 3.方法区内存异常 报错方式 原因 解决思路 生成dump文件三种方式 dump生成 jvis ...

  6. java ppt转图片 内存溢出_Java虚拟机内存及内存溢出异常

    Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外面的人想进来,墙里面的人却想出来. 不知道其他人想出来没,反正我是没想出来,为什么这个JVM的运行时内存要这样设计?. 以下内容 ...

  7. Spark 中 JVM 内存使用及配置详情、spark报错与调优、Spark内存溢出OOM异常

    一般在我们开发spark程序的时候,从代码开发到上线以及后期的维护中,在整个过程中都需要涉及到调优的问题,即一开始需要考虑如何把代码写的更简洁高效调优(即代码优化),待开发测试完成后,提交任务时综合考 ...

  8. 一位面试官询问我:Java中的JVM内存溢出和内存泄露是什么?我这么回答成功拿到了offer

    一位面试官询问我:Java中的JVM内存溢出和内存泄露是什么?我这么回答成功拿到了offer. 墨眉无锋墨家代码 2020-11-22 20:16:50 10525 收藏 56 分类专栏: Java ...

  9. 46栈内存溢出、内存区域(程序计数器、Java 虚拟机栈、本地方法栈、Java 堆、方法区、直接内存、内存溢出)与内存溢出(对象实例化分析)

    46.什么情况下会发生栈内存溢出 46.1.Java 内存区域与内存溢出 46.1.1.内存区域 46.1.1.1.程序计数器 46.1.1.2.Java 虚拟机栈 46.1.1.3.本地方法栈 46 ...

  10. 45.JVM调优策略、常见问题:内存泄漏(年老代堆空间被占满、持久代被占满、堆栈溢出、线程堆栈满、系统内存被占满)优化方法:优化目标、优化GC步骤、优化总结;案例分析(公司系统参数、网上给的配置参数)

    45.JVM调优策略 45.1.常见问题 45.1.1.内存泄漏 45.1.1.1.年老代堆空间被占满 45.1.1.2.持久代被占满 45.1.1.3.堆栈溢出 45.1.1.4.线程堆栈满 45. ...

最新文章

  1. AVR开发 Arduino方法(附四) 参考文献与网址
  2. redis多服务器共享_【数据库】Redis(二)持久化及事务
  3. 日常经典用语、成语及谚语
  4. RedisTemplate value序列化导致的问题
  5. python 两个字典的合并 update
  6. centos7.5 部署flask+nginx+uwsgi+python3
  7. SpringBoot+JWT整合-解决登陆验证问题
  8. 2021年中国乙醛市场趋势报告、技术动态创新及2027年市场预测
  9. sm缩写代表什么意思_PE给水管常见的字母缩写都代表什么?
  10. 算法:Three sum求三个数之和
  11. svn分支合并到主干,主干合并到分支
  12. 原生js实现购物车添加删除商品、计算价格功能
  13. 使用注解失败的原因及解决方法
  14. 关于Protel 2004 绘制电路原理图——元件库的建立
  15. Android 和 iOS 开发的寒冬了?
  16. [ WARN] [1588040435.867625184]: MessageFilter [target=odom ]: Dropped 97.37% of messages so
  17. 约瑟夫环问题(数学递推法)
  18. 详解六大QQ病毒特征及清除
  19. 亚马逊云服务器aws配置ssl https证书
  20. zoomeye爬取前二十页ip+port记录

热门文章

  1. 国人自研开源项目,一款简单易用的 GitLab 替代品
  2. Connect Four四子棋c++程序 - 善后处理(3)
  3. Hive-WARN: Establishing SSL connection without server‘s identity verification is not recommended. Ac
  4. python的shape和reshape_一文浅显易懂:Python中shape()和reshape()的用法和区别
  5. Delphi 编译的程序在win10中怎样默认以管理员身份运行
  6. [phyton]文件的简单读写练习
  7. 你想要的宏基因组-微生物组知识全在这(2020.7)
  8. day3.python基础中下
  9. C++后台开发面试常考
  10. 股票历史数据-股票历史数据在线查询系统