今天在用 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,最终解决了问题。

  解决问题的关键点在三处:

  1. OutOfMemoryError: java heap space ,可以通过上调Xmx解决。
  2. OutOfMemoryError 如果是由于本地方法产生的,应该下调Xmx。这种解决问题的技巧在周志明的《深入理解java虚拟机》中有讲到。
  3. 学会用jconsole去监控内存使用情况。

  这次最终还残留了一个问题没有解决,为什么只设置-Xmx参数之后,OOME会间歇性出现。我只是猜想原因,真正的原因还有待验证。并且我还没有想到好的验证方法,希望有经验的朋友能帮忙指出!

调整JVM堆内存解决OutOfMemoryError的更多相关文章

  1. 【转】JVM 堆内存设置原理

    堆内存设置 原理 JVM堆内存分为2块:Permanent Space 和 Heap Space. Permanent 即 持久代(Permanent Generation),主要存放的是Java类定 ...

  2. [转]JVM 堆内存设置原理

    堆内存设置 原理 JVM堆内存分为2块:Permanent Space 和 Heap Space. Permanent 即 持久代(Permanent Generation),主要存放的是Java类定 ...

  3. JVM 堆内存设置原理

    堆内存设置 原理 JVM堆内存分为2块:Permanent Space 和 Heap Space. Permanent 即 持久代(Permanent Generation),主要存放的是Java类定 ...

  4. JVM 堆内存设置原理(转)

    堆内存设置 原理 JVM堆内存分为2块:Permanent Space 和 Heap Space. Permanent 即 持久代(Permanent Generation),主要存放的是Java类定 ...

  5. 巩固java(二)----JVM堆内存结构及垃圾回收机制

    前言:        我们在运行程序时,有时会碰到内存溢出(OutOfMemoryError)的问题,为了解决这种问题,我们有必要了解JVM的内存结构和垃圾回收机制. 正文: 1.JVM堆内存结构   ...

  6. JDK8中JVM堆内存划分

    一:JVM中内存 JVM中内存通常划分为两个部分,分别为堆内存与栈内存,栈内存主要用运行线程方法 存放本地暂时变量与线程中方法运行时候须要的引用对象地址. JVM全部的对象信息都 存放在堆内存中.相比 ...

  7. jvm堆内存和GC简介

    最近经常遇到jvm内存问题,觉得还是有必要整理下jvm内存的相关逻辑,这里只描述jvm堆内存,对外内存暂不阐述. jvm内存简图 jvm内存分为堆内存和非堆内存,堆内存分为年轻代.老年代,非堆内存里只 ...

  8. JVM堆内存监测的一种方式,性能调优依旧任重道远

    上月,由极客邦.InfoQ和听云联合主办2016 APMCon中国应用性能管理大会圆满落下帷幕.会上,Java冠军Martijn Verburg进行了一场Java and the Machine的分享 ...

  9. JVM堆内存设置

    今天碰到了一个题目,讲的是关于堆内存的问题,题目如下   下面哪种情况会导致持久区jvm堆内存溢出? A.循环上万次的字符串处理 B.在一段代码内申请上百M甚至上G的内存 C.使用CGLib技术直接操 ...

随机推荐

  1. poj 3270(置换 循环)

    经典的题目,主要还是考思维,之前在想的时候只想到了在一个循环中,每次都用最小的来交换,结果忽略了一种情况,还可以选所有数中最小的来交换一个循环. Cow Sorting Time Limit: 200 ...

  2. 【BZOJ4817】[Sdoi2017]树点涂色 LCT+线段树

    [BZOJ4817][Sdoi2017]树点涂色 Description Bob有一棵n个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路径的权值是:这条路 ...

  3. 【BZOJ3994】[SDOI2015]约数个数和 莫比乌斯反演

    [BZOJ3994][SDOI2015]约数个数和 Description  设d(x)为x的约数个数,给定N.M,求   Input 输入文件包含多组测试数据. 第一行,一个整数T,表示测试数据的组 ...

  4. HUST 1354 - Rubiks (DP)

    1354 - Rubiks 时间限制:1秒 内存限制:64兆 452 次提交 102 次通过 题目描述 Isun is a genius. Not only he is an expert in al ...

  5. 关于后台传来的json是含英文字母的string

    最近帮朋友写东西,遇上一个比较坑的后台,传来的json是字符串,并且还伴有英文字符,类似 callback({xxx:xxx,xxx:xxx}),我打印了一下后台传来的数据格式,发现时string,所 ...

  6. 将DataTable转换成Json格式

    方法一: 将DataTable数据拼接成json字符串,方法如下: ///<summary> /// dataTable转换成Json格式 ///</summary> ///& ...

  7. Introduction to Mathematical Thinking - Week 6 - Proofs with Quantifieers

    Mthod of proof by cases 证明完所有的条件分支,然后得出结论. 证明任意 使用任意 注意,对于一个任意的东西,你不知道它的具体信息.比如对于任意正数,你不知道它是 1 还是 2等 ...

  8. Django 之 权限系统(组件)

    参考: http://www.cnblogs.com/yuanchenqi/articles/7609586.html

  9. Ubuntu16.04安装Chrome浏览器及解决root不能打开的问题

    1. 安装桌面(emmm,不知道是否只执行第二个命令就行) # apt-get install gonme# apt-get install ubuntu-desktop2. 安装Chrome浏览器 ...

  10. PyNN:神经网络模拟器的通用接口

    PyNN:神经网络模拟器的通用接口 计算神经科学已经产生了用于模拟神经元网络的多样化软件,同时具有消极和积极的后果.一方面,每个模拟器都使用自己的编程或配置语言,导致将模型从一个模拟器移植到另一个模拟 ...