实习日常的点点滴滴记录(Java应用内存泄漏相关开发规范+JVM参数调优)------好记性不如烂笔头--慢慢积累,厚积薄发

1.开发规范

建议 原理
及时关闭资源 在使用文件、IO流、数据库连接等不会自动释放的资源时,应该在使用完毕后马上将其关闭。关闭资源的代码应在try…catch…finally的finally内执行,否则可能造成资源无法释放。
减少静态变量的使用 静态变量是在加载类时分配的,只有在加载该类的类加载器本身被释放时才会被垃圾回收, 这导致静态变量通常在程序运行期间很难被回收
严格控制循环中的内存增长 尽可能避免在循环中分配大量内存,使用动态内存分配函数时,要确保对象会被及时释放
避免重写finalize() 重写finalize()方法时,该类的对象不会立即被垃圾收集器收集,如果finalize()方法的代码有问题,那么会潜在的引发OOM
ThreadLocal使用及时remove() 线程的生命周期无法结束,会一直存在:Current Thread Refefence -> Thread -> ThreaLocalMap -> Entry -> value -> Object的强引用,这样value所强引用的Object对象迟迟得不到回收,就会导致内存泄漏
慎用单例模式 和静态集合导致内存泄漏原因类似,因为单例的静态特性,它的生命周期和 JVM 的生命周期一样长,所以如果单例对象持有外部对象引用,那么这个外部对象也不会被回收,那么就会发生内存泄漏
变量的作用域应该与使用域匹配 让变量在使用后第一时间就可以被释放;对于不再需要使用的对象,显式地将其赋值为null
避免在长生命周期的对象中持有短生命周期对象的引用 例如使用静态的HashMap、LinkedList等集合对象,那么它们的生命周期与程序一致,即使容器中的对象是短生命周期的,在程序结束之前也不能被释放,从而造成内存泄漏。

2.应用JVM参数

●JVM内存计算模型可粗略表示为:
JVM总内存 = 堆内存(Xmx) + 方法区内存(MaxPermSize) + 栈内存(Xss)*线程数 + 直接内存(MaxDirectMemorySize) + 若干难控制的其它堆外内存 + 虚拟机内存

●JVM参数调优:
○降低线程数,例如减少dubbo线程池大小,可降低应用启动后的初始内存。
【强烈建议】降低堆内存上限,有助于缓解OS OOM,尤其适用于没有Full GC就发生OS OOM的场景。2C4G配置服务器的JVM(JDK1.8)内存调优可从以下配置起步:
-Xms1664m -Xmx1664m -Xss512k -XX:NewRatio=1 -XX:MetaspaceSize=384m -XX:MaxMetaspaceSize=384m -XX:MaxDirectMemorySize=256m

○作为进一步的措施,可尝试对GC策略进行调优(JDK1.8),例如可试用CMS GC对Full GC发生的时机进行控制,在老年代扩展到上限之前回收内存,减少OS OOM。
-XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=75 -XX:+UseCMSInitiatingOccupancyOnly

如果应用集群节点数量较多且负载不高,可尝试减少节点数量并增加内存配置,并优先考虑内存密集型型号,例如2核8G

3.优化案例

问题原因/解决方案
1.消息处理场景下,由于代码配置问题导致大量消息消费失败,且存在出错重试的逻辑, 放大了出错次数,导致内存溢出。(可能存在出错路径下未及时关闭资源的情况)
修复代码配置问题
2.使用redission发生连接异常导致mConcurrentHashMap中存在的对象增长进而导致fullgc,内存增长
查找redission相应issue,升级3.13.6版本
3.1.应用端缓存的业务规则过多;
2.堆内存配置过大,应用频繁发生OS 内存告警,却几乎从来没有Full GC
1.优化代码,减少缓存量
2.降低堆内存大小,使用CMS GC, 让Full GC在OS OOM之前发生。
更多案例积累中…

你可能感兴趣的:(实习,jvm,java,开发语言)