调整JVM堆内存解决OutOfMemoryError
今天在用 processing(http://zh.wikipedia.org/wiki/Processing) 编写处理 midi 文件的程序的时候,遇到了一个问题。程序主要是读取分析 midi ,然后用波形模拟 midi 中的信息,最后记录相应内容,创建 wav 文件。在使用 WaveFileWriter 写文件的时候,因为波形数据较多,使用 new byte[139708800] 创建了一个大小约为134M的 byte 数组,导致程序抛出 java.lang.OutOfMemoryError: Java heap space。

起初我想到可能原因是 JVM 的 HeapSize 大小不够,在 cmd 中查看,发现初始大小是下图这样的。也就是初始堆大小为 16777216 bits,也就是16M;堆的最大值是268435456 bits,也就是256M。而我需要创建的byte数组是134M,很可能heap space会不够。于是我就在系统变量里添加了"_JAVA_OPTIONS",将值设为"-Xmx1024m"。

起初我以为经过这样的设置,应该就没有问题了。但是事实情况是,我重新运行了几次程序,有时候不会OOME,有时候会OOME。于是我就用jconsole去监控JVM内存使用情况,发现不管是否抛出OOME,堆内存都分配了134M的空间给我的byte数组。(jconsole是安装jdk时候自带的,如果配置了java环境变量,可以直接在cmd中输入"jconsole"即可启动)


于是我猜想,是不是因为没有将 -Xms 和 -Xmx 设置为一样,从而导致垃圾回收之后,虚拟机重新分配内存不及时,导致错误率先抛出?按照 Java SE hotspot 的说明文档,如果 InitialHeapSize 和 MaxHeapSize 不一样,那么在运行过程中 JVM 会自动调整内存大小,默认值是上升20%。(具体值可在cmd中查看)这样的话,为了分配134M的内存,需要经过多次增长,所以有时内存重新分配快,就没有OOME,有时候重新分配慢,就会有OOME。不管怎样,为了避开这个问题,我就将"_JAVA_OPTIONS"系统变量的值设定为"-Xms1024m -Xmx1024m"。不过这次出现了新的问题,也是OOME,但是不是java heap space,而是outputstream.write(byte[]) (native method) 出现了OOME。原因是我将JVM的内存设置太大,导致Direct Memory不够了,执行本地方法的时候内存不足。于是我重新调整JVM的内存大小为512M,最终解决了问题。
解决问题的关键点在三处:
- OutOfMemoryError: java heap space ,可以通过上调Xmx解决。
- OutOfMemoryError 如果是由于本地方法产生的,应该下调Xmx。这种解决问题的技巧在周志明的《深入理解java虚拟机》中有讲到。
- 学会用jconsole去监控内存使用情况。
这次最终还残留了一个问题没有解决,为什么只设置-Xmx参数之后,OOME会间歇性出现。我只是猜想原因,真正的原因还有待验证。并且我还没有想到好的验证方法,希望有经验的朋友能帮忙指出!
调整JVM堆内存解决OutOfMemoryError的更多相关文章
- 【转】JVM 堆内存设置原理
堆内存设置 原理 JVM堆内存分为2块:Permanent Space 和 Heap Space. Permanent 即 持久代(Permanent Generation),主要存放的是Java类定 ...
- [转]JVM 堆内存设置原理
堆内存设置 原理 JVM堆内存分为2块:Permanent Space 和 Heap Space. Permanent 即 持久代(Permanent Generation),主要存放的是Java类定 ...
- JVM 堆内存设置原理
堆内存设置 原理 JVM堆内存分为2块:Permanent Space 和 Heap Space. Permanent 即 持久代(Permanent Generation),主要存放的是Java类定 ...
- JVM 堆内存设置原理(转)
堆内存设置 原理 JVM堆内存分为2块:Permanent Space 和 Heap Space. Permanent 即 持久代(Permanent Generation),主要存放的是Java类定 ...
- 巩固java(二)----JVM堆内存结构及垃圾回收机制
前言: 我们在运行程序时,有时会碰到内存溢出(OutOfMemoryError)的问题,为了解决这种问题,我们有必要了解JVM的内存结构和垃圾回收机制. 正文: 1.JVM堆内存结构 ...
- JDK8中JVM堆内存划分
一:JVM中内存 JVM中内存通常划分为两个部分,分别为堆内存与栈内存,栈内存主要用运行线程方法 存放本地暂时变量与线程中方法运行时候须要的引用对象地址. JVM全部的对象信息都 存放在堆内存中.相比 ...
- jvm堆内存和GC简介
最近经常遇到jvm内存问题,觉得还是有必要整理下jvm内存的相关逻辑,这里只描述jvm堆内存,对外内存暂不阐述. jvm内存简图 jvm内存分为堆内存和非堆内存,堆内存分为年轻代.老年代,非堆内存里只 ...
- JVM堆内存监测的一种方式,性能调优依旧任重道远
上月,由极客邦.InfoQ和听云联合主办2016 APMCon中国应用性能管理大会圆满落下帷幕.会上,Java冠军Martijn Verburg进行了一场Java and the Machine的分享 ...
- JVM堆内存设置
今天碰到了一个题目,讲的是关于堆内存的问题,题目如下 下面哪种情况会导致持久区jvm堆内存溢出? A.循环上万次的字符串处理 B.在一段代码内申请上百M甚至上G的内存 C.使用CGLib技术直接操 ...
随机推荐
- <转> python的垃圾回收机制
Python的GC模块主要运用了“引用计数”(reference counting)来跟踪和回收垃圾.在引用计数的基础上,还可以通过“标记-清除”(mark and sweep)解决容器对象可能产生的 ...
- android菜鸟学习笔记31----Android使用百度地图API(二)获取地理位置及地图控制器的简单使用
1.获取当前地理位置: Android中提供了一个LocationManager的类,用于管理地理位置.不能通过构造函数获取该类的实例,而是通过Context的getSystemService(): ...
- pycharm如何自定义模板?
按照上图箭头方向设置即可.
- hive表信息查询:查看表结构、表操作等
转自网友的,主要是自己备份下 有时候不记得! 问题导读:1.如何查看hive表结构?2.如何查看表结构信息?3.如何查看分区信息?4.哪个命令可以模糊搜索表 1.hive模糊搜索表 show tabl ...
- RedHat6/Centos6.5安装mongodb php driver
条件: 安装apache 安装php 1.下载mongodb phh driver 下载地址:pecl wget http://pecl.php.net/get/mongo-1.5.8.tgz 2.解 ...
- ECMAScript6箭头函数ArrowFunction"=>"
一.说明 ECMAScript6可以用箭头"=>"定义函数.x => x * x或(x) => {return x * x;}与匿名函数function(x){r ...
- cmd文件和bat文件有什么区别
第一次遇到后缀是cmd的文件, 记录下与bat文件的区别 本质上没有区别,都是简单的文本编码方式,都可以用记事本创建.编辑和查看. 两者所用的命令行代码也是共用的,只是cmd文件中允许使用的命令要比b ...
- curl学习总结
1.接口 function interface($postfields=array(),$url){ //设置post请求HTTP头字段的数组 $httpheader ...
- Python 网络编程——socket
一 客户端/服务器架构 客户端(Client)服务器(Server)架构,即C/S架构,包括 1.硬件C/S架构(打印机) 2.软件C/S架构(web服务) 理想/目标状态—— 最常用的软件服务器是 ...
- Linux 路径与命令搜寻顺序
以相对/绝对路径运行命令,例如『 /bin/ls 』或『 ./ls 』: 由 alias 找到该命令来运行: 由 bash 内建的 (builtin) 命令来运行: 透过 $PATH 这个变量的顺序搜 ...