JVM内存泄漏导致内存溢出(OOM)的场景

一、概念

1. 内存泄漏:对象使用完之后,没有按照预期被GC回收,一直留在内存中

2. 内存溢出:大量对象一直留在内存中,导致内存不够用(OOM),影响正常的程序运行

二、内存泄漏的场景

1. 内存中数据量太大,比如一次性从数据库中取出来太多数据

2. 静态集合类中对对象的引用,在使用完后未清空(只把对象设为null,而不是从集合中移除),使JVM不能回收,即内存泄漏

3. 静态方法中只能使用全局静态变量,而如果静态变量又持有静态方法传入的参数对象的引用,会引起内存泄漏

4. 代码中存在死循环,或者循环过多,产生过多的重复的对象

5. JVM启动参数内存值设置过小

a. 堆内存:JVM默认为64M,-Xms堆的最小值, -Xmx堆的最大值,OutOfMemoryError: java heap space

b. 栈内存:-Xss,StackOverflowError,栈太深

c. 永久代内存:-XX:PermSize,-XX:MaxPermSize,OutOfMemoryError: PermGen space,加载的类过多

6. 监听器:addXXListener,没有remove

7. 各种连接没有关闭:例如数据库连接、网络连接

8. 单例模式:如果单例对象持有外部对象的引用,那么外部对象将不会被回收,引起内存泄漏

9. 一个类含有静态变量,这个类的对象就无法被回收

10. ThreadLocal

三、解决思路

1. 修改JVM启动参数,直接增加内存

2. 检查错误日志

3. 检查代码中有没有一次性查出数据库所有数据

4. 检查代码中是否有死循环

5. 检查代码中循环和递归是否产生大量重复对象

6. 检查List/Map等集合,是否未清除

7. 使用内存查看工具

四、代码优化

1. 主动释放无用的对象

2. 尽量使用StringBuilder代替String

3. 尽量少用静态变量,因为静态变量是类的,GC不会回收

4. 避免创建大对象和同时创建多个对象,例如数组,因为数组的长度是固定的

5. 对象池技术

五、JVM堆内存溢出后,其他线程可否继续工作?

1. 当前线程OOM后,如果终止,会发生GC,其他线程可以继续工作

2. 如果线程OOM后,没有终止,其他线程也会OOM

https://www.cnblogs.com/200911/p/3965108.html

猜你喜欢

转载自www.cnblogs.com/june0816/p/11117959.html