思路: 1、什么对象消耗内存最大; 2、是否创建了太多的线程; 3、新生的、老年代现在内存使用情况,确认是不是整体内存分配太小了; 4、实时查看新生的、老年代内存使用情况,GC情况 5、代码层检查,是否有大对象创建?需要调用close()或dispose()来回收的资源是否回收了? 操作: 1、执行“jmap -histo:live 10765 | more”命令,以表格的方式显示存活对象的信息(已按对象所占bytes大小进行降序排列): 其中,10765为进程ID,更多用法,通过“man jmap”寻求帮助。 占内存最多的对象类型是org.apache.logging.log4j.core.async.RingBufferLogEvent, 总共18874368byte (18M),例子中属于正常使用。 tips:如果发现某类对象占用内存很大(几个G的大小),很可能是有问题的。 基本都是因为:该类对象创建太多,且一直未释放。比如:使用完IO资源后,未调用close()接口关闭、释放资源;又比如:消费者消费速度慢(或停止消费了),而生产者不断往队列中投递任务,导致队列中任务累积过多,任务对象占用内存太多而产生OutOfMemoryError; 2、执行“pstree -p 10765 | wc -l”,查看进程内的线程数 其中,10765为进程ID。 每个线程需要分配线程栈内存,创建线程太多,可能导致OutOfMemoryError。 3、执行“jmap -heap 10765”,查看堆(新生代、老年代)内存分配大小及使用情况 4、执行“jstat -gc 10765 1000”,查看各个区内存使用情况及GC情况 其中,10765为进程ID,1000为数据刷新间隔的毫秒数 具体字段含义,通过“man jstat”寻求帮助。 主要查看: EC:Eden区容量,EU:Eden区已使用量,OC:Old区容量,OU:Old区已使用量; YGC:YongGC次数,YGCT:YongGC耗时,FGC:FullGC次数,FGCT:FullGC耗时; 5、代码检查,要求相关同学做codereview