StringBuffer的内存溢出实例(转自Ahuaxuan的文章)

Ahuaxuan在公司属于大牛级别的人物,技术理解深入,口才更好,人品也好。

 

转载这篇文章,想做个JVM方面的专题:

 

Ahuaxuan的这篇文章写得很好,做个转载,过段时间准备制成PDF。

 

 

 

/*

  • @author: ahuaxuan
  • @date: 2010-4-30
  • /

在内存充裕的情况下的OOM

 


理解本文的前提是理解JVM的内存模型:包括


perm, old, young(eden, from(s0), to(s1)),
然后理解young中的垃圾搜集算法(拷贝算法,尤其是eden, from(s0),
to(s1)它们分别扮演什么样的角色,为什么任意时间中from和to中必须要有一个是空的), old里的垃圾搜索算法(常见的有:标记压缩算法).


正文:

 

最近一台测试服务器抛出了OOM的错误,本着不放过一切问题的原则,ahuaxuan把这个OOM研究了一番,最后得出了令人意想不到的结论.


charpter 1, 现象


       看到这个OOM的信息之后,ahuaxuan的第一反应是,内存是否真的不够用了,于是使用jmap查看了一下内存的情况,如下:


我们的测试服务器给JVM进程分配的空间是4G,但是从上图中,我们可以看出内存并没有完全用完,尤其是From和TO这两个suvivor空间居然还有900M的空间剩余. Eden 也有112M的空间剩余,Old有288M的空间剩余.


这个不像是空间不足的情况.除非我们的对象真的有这么大,大到超过288M,不管eden还是old都放不下.一个对象要超过300M,那这是一个什么样的对象呀,初步分析,这个对象应该是一个byte数组或者char数组.


charpter2 大对象来源

         为了追到这个问题,接下来就是把heap的dump信息拿出来,通过 jmap -dump:format=b,file=heap.bin <pid> 把当时的这个进程的dump拿了下来(2.7G).

然后用MAT打开一看.


内存基本被byte和char霸占了.寻找这些byte和char的root.得到


 

           嘿,好家伙,360M的对象,还不在少数(还有其他的图,包含了其他的大对象,就不列出了,主角就是上面的char[]), 而且这些对象是由Lucene创建的,经查,lucene会将索引中的field装载入内存,看似也是合理的,但是不合理的地方是它出现在了 RAMInputStream这个类中,因为按照jackrabbit的逻辑(ahuaxuan曾经写过17篇文章来阐述jackrabbit中的搜索模 块,详情查看: http://ahuaxuan.iteye.com/category/65829 ).这里ahuaxuan稍微阐述一下jackrabbit的搜索模块中是怎么使用RAMDirectory的:

 

新 的索引请求到达索引模块,建索引完成之后,jackrabbit不会立即将索引数据刷入磁盘, 而是放在内存中,然后当内存中的数据满足一定量之后(可以在配置文件中设置),这批数据会被一起刷到磁盘中,也就是从RAMDirectory中刷到 FSDirectory中,而刚才讲到满足一定的量,其实默认值是100, 也就是说RAMDirectory中最多保持了100个Document.


问题就在这里,100个Document能有360M的field?

这个可能性微乎其微. 如果不是这360M的量有问题,那么就是这100个Document的数量有问题,也许根本就超过了100个.


回过头来我们再来看看上面的逻辑:

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值