为什么80%的码农都做不了架构师?>>>   

JVM规范规定,除了程序计数器,虚拟机其他内存区域均会发生内存溢出的可能,OutOfMemoryError(OOM)

原文地址:http://www.begincode.net/blog/62  我的网站,欢迎大家多提意见

本文目的:

1、通过代码人为造成OOM,让大家跟了解JVM运行时各区存储的内容。

2、通过demo让大家实际开发过程中,能够根据异常判断是那个内存区域发生的溢出,

3、让大家了解到什么样的代码会产生OOM,开发中能够尽量规避。

前提:

先和大家介绍一下eclipse如何设置JVM参数,Xms 最小堆内存,Xmx最大堆内存,

HeapDumpOnOutOfMemoryError:发生内存溢出时生成堆转储快照

一、JAVA堆内存溢出

代码实例,来自<<深入理解JVM虚拟机>>

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

运行结果如下,发生内存溢出,在OutOfMemoryError后面会跟着 Java heap space 提示是堆内存溢出,

同时生成 java_pid10308.hprof 文件

该文件可以用分析工具MAT进行分析,安装链接http://www.begincode.net/blog/45 也可以用其他工具,

java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid10308.hprof ...
Heap dump file created [27883798 bytes in 0.497 secs]

通过工具可以分析是内存泄露还是内存溢出,如果不存在泄露,那就是存在着很多对象实例无法回收,可以通过分析查看是那些对象,是否必须存活,如果必须存活在考虑适当调整JVM堆参数,如Xmx Xms等在以后的文章中会在此介绍。

二、虚拟机栈和本地方栈溢出(栈溢出)

1、虚拟机栈

虚拟机栈溢出,理论上分为两种,一种是线程请求的栈深度大于虚拟机允许的最大深度,另外一种是申请的空间不足。

因为虚拟机栈记录的是局部变量(方法变量)和函数调用栈针,则产生堆栈溢出一般是函数调用深度,如递归类或者

方法A调用方法B,方法B调用方法C这样调用深度超过了虚拟机允许的最大深度,

JVM参数设置为如下,Xss128k  Xss是堆栈大小

-Xms20m -Xmx20m -Xss128k -XX:+HeapDumpOnOutOfMemoryError

demo如下

public class TestOOM {static int stackIndex = 0;public   void testStackOverFlow(){stackIndex++;testStackOverFlow();}public static void main(String[] args) throws Throwable  {try{TestOOM oom = new TestOOM();oom.testStackOverFlow();}catch(Throwable e){System.out.println("堆栈深度(迭代次数):"+stackIndex);throw e;}}
}

执行结果,堆栈深度达到983,堆栈溢出,并会给出具体是类,方法,发生的错误

堆栈深度(迭代次数):983
Exception in thread "main" java.lang.StackOverflowErrorat zgwx.TestOOM.testStackOverFlow(TestOOM.java:9)at zgwx.TestOOM.testStackOverFlow(TestOOM.java:10)
相同参数情况下如果修改递归的方法,在方法内创建几个变量大家再看下结果。
public   void testStackOverFlow(){stackIndex++;int str = 12;int str2 = 12;int str3 = 12;int str4 = 12;int str5 = 12;int str6 = 12;int str7 = 12;int str8 = 12;testStackOverFlow();}

执行结果如下,迭代次数明显减少,说明局部变量占用了堆栈的空间

堆栈深度(迭代次数):579
Exception in thread "main" java.lang.StackOverflowErrorat zgwx.TestOOM.testStackOverFlow(TestOOM.java:9)at zgwx.TestOOM.testStackOverFlow(TestOOM.java:18)

2、本地方法栈,本地方法栈可以通过创建线程的方式来实现溢出,因为java线程是映射到操作系统内核上,所以线程会调用本地方法,造成本地方法栈的溢出

本机环境没测试出来,机器卡死了,大家可以自己试试尽量多创建线程,就会撑爆本地方法栈

下面是找来的例子,没见到效果,都死卡死机告终

public class Test {private void runAlways(){while(true){}}public void createThread(){while(true){Thread thread = new Thread(new Runnable(){public void run() {runAlways();}});thread.start();}}public static void main(String[] args) {Test test = new Test();test.createThread();}}

三、直接本机内存溢出

本机内存溢出可以无限制申请空间即可,用nio的申请缓冲区方式

public static void main(String[] args) {List list = new ArrayList();while(true){ByteBuffer byteBuffer = ByteBuffer.allocateDirect(1024*2048);list.add(byteBuffer);}}

执行结果如下,OutOfMemoryError后面的提示,Direct buffer memory 说明了直接缓冲区,

Exception in thread "main" java.lang.OutOfMemoryError: Direct buffer memoryat java.nio.Bits.reserveMemory(Bits.java:658)at java.nio.DirectByteBuffer.<init>(DirectByteBuffer.java:123)

四、方法区(永久代)溢出

方法区存储的是加载的类信息,常量,我们就循环创建字符串常量,让方法区溢出

为了尽快溢出,jvm参数设置永久代参数5M: -XX:PermSize=5m  -XX:MaxPermSize=5m

代码如下:

public static void main(String[] args) {List list = new ArrayList();int i = 0;while(true){list.add((String.valueOf(i++)).intern());}}

运行结果如下:OutOfMemoryError后面提示 PermGen space ;改代码在jdk6及以下版本能够报出如下异常,jdk7高版本及以上部分jvm已经逐渐开始取消永久代的原因,只会报出堆内存异常

Exception in thread "main" java.lang.OutOfMemoryError: PermGen spaceat java.lang.String.intern(Native Method)at com.TestSocket.main(TestSocket.java:12)

转载于:https://my.oschina.net/UpBoy/blog/514926

JVM内存溢出分析-实战JVM(二)相关推荐

  1. jvm内存溢出分析实践案例:javax.crypto.JceSecurity大量BouncyCastleProvider实例无法被回收

    MAT分析结果: 模拟运行14分钟,循环进行8000多次加解密的对比:

  2. JVM 调优实战--jmap的使用以及内存溢出分析

    目录 jmap的使用以及内存溢出分析 查看内存使用情况 查看内存中对象数量及大小 将内存使用情况dump到文件中 通过jhat对dump文件进行分析 通过MAT工具对dump文件进行分析 MAT介绍 ...

  3. 生产环境JVM内存溢出案例分析!

    点击上方 好好学java ,选择 星标 公众号 重磅资讯.干货,第一时间送达 今日推荐:Nginx 为什么快到根本停不下来? 个人原创100W+访问量博客:点击前往,查看更多 来源:blog.csdn ...

  4. 生产环境 JVM 内存溢出案例分析

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 来源:blog.csdn.net/prestigeding ...

  5. 生产环境JVM内存溢出案例分析

    如果我们所在公司的业务量比较大,在生产环境经常会出现JVM内存溢出的现象,那我们该如何快速响应,快速定位,快速恢复问题呢? 本文将通过一个线上环境JVM内存溢出的案例向大家介绍一下处理思路与分析方法. ...

  6. java内存溢出分析工具:jmap使用实战

    java内存溢出分析工具:jmap使用实战 在一次解决系统tomcat老是内存撑到头,然后崩溃的问题时,使用到了jmap.  1 使用命令  在环境是linux+jdk1.5以上,这个工具是自带的,路 ...

  7. Tomcat中JVM内存溢出及合理配置(转:http://blog.csdn.net/ye1992/article/details/9344807)

    Tomcat本身不能直接在计算机上运行,需要依赖于硬件基础之上的操作系统和一个Java虚拟机.Tomcat的内存溢出本质就是JVM内存溢出,所以在本文开始时,应该先对Java JVM有关内存方面的知识 ...

  8. jvm 内存溢出问题排查方法

    如果你做TCP通讯或者map集合操作,并发处理等功能时,很容易出现 Java 内存溢出的问题.本篇文章,带领大家深入jvm,分析并找出jvm内存溢出的代码. jvm中除了程序计数器,其他的区域都有可能 ...

  9. tomcat中 JVM 内存溢出及合理配置

    Tomcat本身不能直接在计算机上运行,需要依赖于硬件基础之上的操作系统和一个Java虚拟机.Tomcat的内存溢出本质就是JVM内存溢出,所以在本文开始时,应该先对Java JVM有关内存方面的知识 ...

最新文章

  1. Django基础-数据分页
  2. Python 可视化近 90 天的百度搜索指数 + 词云图
  3. sql,EXISTS用法
  4. 操作系统:第一章 计算机系统概述
  5. 【数据库】数据模型(类型全+白话讲解)
  6. Git 常用命令(二)
  7. mysql cluster 设置单向复制_mysql单向主从配置
  8. vbs连接oracle11,vbs连oracle数据库
  9. 小米装android4.4,在VM已安装Android4.4 连接小米手环 网络设置
  10. 4-2 数据模型的生成
  11. input输入框提示从数据库查出来的一堆数据
  12. Android7.1开机启动脚本
  13. WebSphere 集群环境下配置 Quartz集群
  14. 彻底删除linux mbr,如何删除mbr分区表(超详细介绍Linux管理分区技巧)
  15. 3❤️Jenkins从零到壹❤️ :常用功能大全(JAVA 小虚竹)
  16. 有向图的拓扑排序算法JAVA实现。
  17. 不同域名间的session共享
  18. studing(来自转载)
  19. UE4开关门简单记录
  20. 论文阅读中经常出现的“消融研究/实验”

热门文章

  1. windows7旗舰版系统自带组件IIS搭建ftp
  2. 张颐武:周小平的意义
  3. 配置Exchange 2010邮箱和邮件大小限制
  4. Web Form中的Datagrid的自定义分页
  5. 常用Git命令清单。
  6. java怎么显示qt文件后缀,在qt中执行java文件
  7. SpringAMQP--FanoutExchange
  8. MyBatis 源码解读-loadCustomVfs(settings)
  9. Redis中的set应用场景
  10. 自定义线程池-线程池工作流程介绍