线上问题:
1.线上每天定时读取文件(大文件)成MAP,并加载入库,当执行完最后一批 批量提交sql 时,JVM堆内存没释放;
2.因为加了以下堆内存检测,所以,下一次处理文件时,发起不了新的线程处理新任务;
public boolean exceedSize() {
MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();
LOGGER.info("堆内存信息: " + memoryBean.getHeapMemoryUsage());
return memoryBean.getHeapMemoryUsage().getUsed() / 1000 > heapSizeThreshold; // heapSizeThreshold = 3G
}
3.JVM参数配置:-Xms6144M -Xmx6144M -XX:+UseG1GC -XX:ParallelGCThreads=5 -XX:G1HeapRegionSize=32m -XX:G1ReservePercent=10 -XX:MaxGCPauseMillis=800
问题认识:
1.当线程处理完,堆内存没有触发释放的条件
2.之前看过的把xmx和xms设置一致可以让JVM在启动时就直接向OS申请xmx的commited内存,
好处是:
1)避免JVM在运行过程中向OS申请内存
2)延后启动后首次GC的发生时机
3)减少启动初期的GC次数
4)尽可能避免使用swap space
坏处:
堆内存释放不及时
解决方案:
第一、设置-Xms6144M -Xmx6144M参数为:-Xms1024M -Xmx6144M
第二、在发起线程前,检测堆内存时,Object obj = new Object(); // 触发垃圾回收
其他:
上线前,应尽可能准确估计上线情况,做压力测试,使用jdk自带的监控工具多做分析;上线后,不断迭代优化;可以考虑设置MaxHeapFreeRatio/MinHeapFreeRatio参数