首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

实践中的复建27_不要忘了内存空间

2012-12-27 
实践中的重构27_不要忘了内存空间方法在设计中,一般关注的是方法的功能契约,即方法需要什么样的参数,方法

实践中的重构27_不要忘了内存空间
方法在设计中,一般关注的是方法的功能契约,即方法需要什么样的参数,方法运行时会保持什么样的不变量,方法运行后会得到什么样的输出。较少会关注到方法的非功能性特征,典型的为方法的执行时间,方法执行时的内存空间消耗等等。
最近关注到一段代码,因为该段代码是导致OutOfMemoryError的一个因素,所以拿来一看。

 25.00   0.00   0.00   0.36  12.75   2464    0.467     0    0.000    0.467
25.00   0.00   0.00   0.36  12.75   2582    0.488     0    0.000    0.488
  0.00  25.00   0.00   0.36  12.75   2707    0.510     0    0.000    0.510
  0.00  25.00   0.00   0.36  12.75   2787    0.528     0    0.000    0.528
  0.00  25.00  72.48   0.36  12.75   2866    0.550     0    0.000    0.550
25.00   0.00  18.12   0.36  12.75   2918    0.560     0    0.000    0.560
</pre>
?
<p>没有一次full gc,平均一次minor gc在1.8毫秒。</p>
</div>
<br>JDK版本,那个公司的jvm</div>
<p>?</p>
<p>dennis@dennis-laptop:~$ /opt/jdk1.6.0_18/bin/java -version<br>java version "1.6.0_18"<br>Java(TM) SE Runtime Environment (build 1.6.0_18-b07)<br>Java HotSpot(TM) Server VM (build 16.0-b13, mixed mode)<br>dennis@dennis-laptop:~$ uname -a<br>Linux dennis-laptop 2.6.38-8-generic-pae #42-Ubuntu SMP Mon Apr 11 05:17:09 UTC 2011 i686 i686 i386 GNU/Linux<br></p> 10 楼 zhang_xzhi_xjtu 2011-06-09   这个问题抛OOE说起来比较复杂。
楼上的例子之所以没有问题是因为。
1 单线程跑,没有并发。本次循环执行时内存不够回minor GC掉上一个循环申请的内存,
2 GC设置的是什么GC,一般大型系统用CMS GC,由于回收是并行做的,有可能无引用对象还是会占用内存的。
3 内存吃紧的时候,这种无谓的内存申请,有可能是压死骆驼的最后一根稻草。

这里的关键在于并发时,minor GC不掉其他线程的内存,并且提升至OLD,而OLD内存在major GC CMS回收时,是有一段时间处理不到同时并发的内存申请的。

CMS需要更多的内存空间,因为mark phase时程序还是在运行,程序可以申请更多的old空间。在mark phase中,CMS保证标识活对象,但是该过程中,活对象可能转变为垃圾,只能等待下一次GC才能回收。

总而言之:
内存是宝贵的,在可以用确定大小内存完成任务的情况下,采用多申请内存的方式会有OOE的风险。

11 楼 ray_linn 2011-06-09   连enum.values都ooe了...是不是楼主家的所有的代码都要加上staitc hashmap,因此最后导致内存空间不足。


明显在拼凑场景。 12 楼 humaeks 2011-06-09   zhang_xzhi_xjtu 写道这个问题抛OOE说起来比较复杂。
楼上的例子之所以没有问题是因为。
1 单线程跑,没有并发。本次循环执行时内存不够回minor GC掉上一个循环申请的内存,
2 GC设置的是什么GC,一般大型系统用CMS GC,由于回收是并行做的,有可能无引用对象还是会占用内存的。
3 内存吃紧的时候,这种无谓的内存申请,有可能是压死骆驼的最后一根稻草。

这里的关键在于并发时,minor GC不掉其他线程的内存,并且提升至OLD,而OLD内存在major GC CMS回收时,是有一段时间处理不到同时并发的内存申请的。

CMS需要更多的内存空间,因为mark phase时程序还是在运行,程序可以申请更多的old空间。在mark phase中,CMS保证标识活对象,但是该过程中,活对象可能转变为垃圾,只能等待下一次GC才能回收。

总而言之:
内存是宝贵的,在可以用确定大小内存完成任务的情况下,采用多申请内存的方式会有OOE的风险。



前面会的帖子里面,提到来不及回收就很神奇。原因就在于,如果真的确定OOM是在这里引起的,那并发真的不知道要多少个了。
简单点的估算,需要的工作内存=并发数×每个并发需要的内存。由于这个map对每个并发需要的内存的增量是如此的小,但如果确实修改后就不出现oom的话,那么其并发数一定对比起jvm内存限制来说一定非常之大。实际需要调整的,并非这个增量把。 13 楼 dennis_zane 2011-06-09   你说这里可能是压死骆驼的最后一根稻草,那还可以接受,你说这段代码会导致OOM,那就是信口开河。我可以写个并发程序来证明,调用N次也不会OOM。

热点排行