Dav*_*ton 13 java memory jvm memory-management windows-mobile
我正在开发一个在Windows Mobile设备上运行的Java应用程序.为了实现这一目标,我们一直在使用Esmertec JBed JVM,这并不完美,但我们现在仍然坚持使用它.最近我们收到客户关于OutOfMemoryErrors的投诉.在经历了很多事情后,我发现设备有足够的可用内存(大约4MB).
OutOfMemoryErrors总是出现在代码中的同一点,也就是扩展StringBuffer以便向其附加一些字符时.在这个区域添加了一些日志记录后,我发现我的StringBuffer中有大约290000个字符,容量大约是290500.内部字符数组的扩展策略只是将大小加倍,所以它会尝试分配一个数组大约580000个字符.我打印出这段时间的内存使用量,发现它总共使用了大约3.8MB的大约6.8MB(尽管我已经看到总可用内存有时会增加到12MB左右,因此有足够的扩展空间).所以在这一点上,应用程序报告了一个OutOfMemoryError,考虑到仍然有多少,它没有多大意义.
到目前为止,我开始考虑应用程序的运行.基本上发生的事情是我正在使用MinML(一个小的XML Sax Parser)解析XML文件.XML中的一个字段中包含大约300k个字符.解析器从磁盘流式传输数据,默认情况下,它一次只加载256个字符.因此,当它到达相关字段时,解析器将调用处理程序的'characters()'方法超过1000次.每次创建一个包含256个字符的新char [].处理程序只是将这些字符附加到StringBuffer.StringBuffer的默认初始大小只有12,因此当字符附加到缓冲区时,它将不得不增长很多次(每次创建一个新的char []).
我的假设是,虽然有足够的可用内存,因为前面的char []可以被垃圾收集,但是可能没有足够大的连续内存块来适应我想要分配的新数组.也许JVM不够智能,无法扩展堆大小,因为它很愚蠢,认为没有必要,因为显然有足够的可用内存.
所以我的问题是:有没有人有这个JVM的经验,并且可能最终确认或反驳我对内存分配的假设?而且,有没有人有任何想法(假设我的假设是正确的)关于如何改进数组的分配,以便内存不会碎片化?
注意:我已经尝试过的事情:
做这两件事有点帮助,但随着我增加xml数据的大小,我仍然得到相当低的大小(约350kb)的OutOfMemoryErrors.
另外要添加的内容:所有这些测试都是在使用相关JVM的设备上执行的.如果我使用Java SE 1.2 JVM在桌面上运行相同的代码我没有任何问题,或者至少我没有遇到问题,直到我的数据大小达到4MB.
编辑:
我刚试过的另一件事有点帮助我将Xms设置为10M.因此,这可以解决JVM在不应该扩展堆时的问题,并允许我在错误发生之前处理更多数据.
只是为了更新我自己的问题,我发现最好的解决方案是设置最小堆大小(我将其设置为 10M)。这意味着 JVM 永远不必决定是否扩展堆,因此它永远不会(在测试中)因 OutOfMemoryError 而终止,即使它应该有足够的空间。到目前为止,在测试中,我们已经能够将我们解析的数据量增加三倍而不会出现错误,如果我们确实需要的话,我们可能会更进一步。
对于让现有客户满意的快速解决方案来说,这是一个小技巧,但我们现在正在寻找不同的 JVM,如果该 JVM 能更好地处理这种情况,我将报告更新。
归档时间: |
|
查看次数: |
2944 次 |
最近记录: |