今天,发现游戏逻辑服务器内存溢出问题,每隔一定时间就生成java_pidxxxxxx.hprof ,基本1G内存分配不够用了,导致FGC频繁发生。

工具:

MAT ​​Eclipse Memory Analyzer Tool(MAT)分析内存泄漏​

MAT(Memory Analyzer Tool),一个基于Eclipse的内存分析工具,是一个快速、功能丰富的JAVA heap分析工具,它可以帮助我们查找内存泄漏和减少内存消耗。使用内存分析工具从众多的对象中进行分析,快速的计算出在内存中对象的占用大小,看看是谁阻止了垃圾收集器的回收工作,并可以通过报表直观的查看到可能造成这种结果的对象。

2.为什么使用MAT?
    当服务器应用占用了过多内存的时候,会遇到OutOfMemoryError。如何快速定位问题呢?Eclipse MAT的出现使这个问题变得非常简单。它能够离线分析dump的文件数据。
首页:​​​http://www.eclipse.org/mat/​​​ 
插件更新地址:
​​​http://download.eclipse.org/mat/1.0/update-site/​



排查原因:

1.是因为策划引入了一张大地图(2W*3W,),导致瞬间内存膨胀了160M,

2.热加载的时候地图系统内存占用会额外扩大n倍。

左:热加载前,右,热加载后

JVM内存溢出深度分析_热加载

3.冗余属性数据存储

处理:

1.冗余属性数据存储:

把PathInfoConfig的_2xNodes和_4xNodes去掉,基本省下了一半的地图内存占用,

(左边,优化前,右边,优化后 看a部分)

JVM内存溢出深度分析_Memory_02

2.停掉地图数据部分的热加载:

左边:热加载前,右边,热加载后,基本内存占用维持不变.

JVM内存溢出深度分析_热加载_03

3.对PathNode的key 类型String换成 Integer,通过移位来生成key 
x << 16|y 

左边,优化前,右边,优化后,减少了40M左右

            主要是hashmap的key的减少空间

JVM内存溢出深度分析_热加载_04



优化前后做个对比 

获取的堆栈分析文件

1.jmap -dump:format=b,file=/data/log/dump.dat 26822

2.通过JVM自动生成hprof 文件


4.PathNode的x和y 用short够用,value的值目前都为1用byte

发现内存占用都为32(25+7),没有上升的空间,所以这块不优化

JVM在分配内存时是以8 bytes为粒度进行分配


5.过滤掉只有在跨服服务器使用的地图

目前地图内存占用从400+降到了200+



参考文章:​​Shallow heap & Retained heap​


​Java对象内存结构 ​