今天在用 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. staitc_cast,const_cast....

    #include <iostream> using namespace std; int main() { //1.const_cast //const int a = 10; //int ...

  2. SharePoint服务器端对象模型 之 访问文件和文件夹(Part 2)

    4.添加文件夹 文件夹的创建方法在文档库和普通列表中稍有不同. 在文档库中,与一般的集合操作相同,直接使用SPFolderCollection的Add(string name)方法即可添加文件夹,例如 ...

  3. 关于微信小程序下拉出现三个小点

    包子这天看美团外卖的小程序,再瞅瞅自己的背景色,发现,美团下拉的时候有三个小点,但是我自己的校车徐下拉的时候没有三个小点,很是郁闷,于是各种的找各种的找,发现,这三个小点是微信小程序自带的,你只需要设 ...

  4. bat masterNodeRun.bat

    C:\> compare C:\> compare C:\>D:\cmd\wphp.bat C:\> compareReq -- :: TODO StartScript -- ...

  5. 【转】《JAVA与模式》之责任链模式

    <JAVA与模式>之责任链模式 在阎宏博士的<JAVA与模式>一书中开头是这样描述责任链(Chain of Responsibility)模式的: 责任链模式是一种对象的行为模 ...

  6. 【转】hibernate中的映射文件xxx.hbm.xml详解总结

    一.Hibernate映射文件的作用: Hibernate映射文件是Hibernate与数据库进行持久化的桥梁 二,Hibernate映射文件主要内容:     (1).映射内容的定义: Hibern ...

  7. windows 和rhel,centos双系统安装

    1:首先确保你先安装为windows系统,为indows7以上的把. 2:安装好为indows系统后,进入系统后把磁盘分区,分出足够的空间为安装linux. 3:再为windows下使用软碟通等工具制 ...

  8. Python2 socket TCPServer 多线程并发 超时关闭

    在阿里云上测试过,可以直接使用. 用IP和端口发送数据,会返回echo:+接收到的数据 #coding=utf-8 import socket import threading,getopt,sys, ...

  9. 【转】SVN使用教程总结

    看到一篇超赞的文章,原链接:http://www.cnblogs.com/armyfai/p/3985660.html SVN简介: 为什么要使用SVN? 程序员在编写程序的过程中,每个程序员都会生成 ...

  10. python之路(sed,函数,三元运算)

    python之路(sed,函数,三元运算) 一.sed集合 1.set无序,不重复序列 2.创建 se = {11,22,33,33,44} list() #只要是一个类加上()自动执行 list _ ...