对生产环境内存溢出的分析1

昨天下午,生产环境168服务器突然报内存溢出.临时抓了jvm快照.重启解决.
今天分析jvm快照.一眼就发现有对象貌似存在异常.DictSegment对象在JVM中有60W+个实例化的对象.
 
    凭经验,一般的JVM溢出都是有对象没有处理好.GC没有回收,导致在JVM里越来越多导致.所以首先排查调用这个类的方法.
    检查代码,发现只有一个类IndexCreateUtil使用到了DictSegment.方法本身的实现上没有问题.网上的demo方法都是这样使用的.
    实践出真知.自己写个测试类.
public class TestIndexCreateUtil2 {
@Test
public void testSplitBySegmenterStringBooleanBoolean() {
User user = new User();
testFenCi2();
try {
System.gc();
// 先不要停止,抓内存使用情况
Thread.sleep(1000000l);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
 
private void testFenCi2(){
String text = "让战士们过一个欢乐祥和的新春佳节。";
// 创建分词对象
StringReader reader = new StringReader(text);
Role role = new Role();
IKSegmenter ik = new IKSegmenter(reader, true);// 当为true时,分词器进行最大词长切分
Lexeme lexeme = null;
try {
while ((lexeme = ik.next()) != null) {
System.out.println(lexeme.getLexemeText());
}
} catch (IOException e) {
e.printStackTrace();
} finally {
reader.close();
}
}
}
    在System.gc();行加断点.抓取JVM发现.执行到System.gc();时.特意加的role 对象还是存在的,但从Eclipse里没法查看了,这应该是还没有执行过GC导致的.另一个更重要的是.DictSegment类有60W+个实例化的对象.
    再次问度娘,调用方法都是对的,大概看了一下,感觉跟IKAnalyzer本身的分词算法可能有关.
    换一个思路.使用IKAnalyzer的作用就是加一些tag.没有使用其他比较高深的东西.那换一个分词软件行不行?
    找到度娘比较推荐的ansj测试.功能可以实现.也没有产生几十万个相同的类对象.再看内存使用.悲剧了.一句分词,内存直接从10M不到飙升到接近100M.而IKAnalyzer内存变动在10M以内的.
    
     综合考虑.还是不换IKAnalyzer了.在此标记一下.抓取到的JVM快照中如果有60W+个DictSegment对象.是正常的(但确实有点奇葩:).
    JVM溢出的原因待继续查找.

猜你喜欢

转载自sanyecao2314.iteye.com/blog/2233123