除了程序计数器其余每个JVM内存区域都可能会造成内存溢出。

1、堆内存耗尽,对象越来越多。

2、方法区内存耗尽,加载的类越来越多,很多框架都会在运行期间产生新的类

3、虚拟机栈累积,每个线程最多会占用1M内存,线程树越来越多,而长时间不运行不销毁。

4、虚拟机栈内部,方法调用次数过多。

 

 

 

 

1、长生命周期持有短声明周期的对象,尽管短生命周期不再使用,但是由于长生命周期一直存在,导致不能被回收

2、各种连接,如果不进行close很多的对象都不会被回收。

3、变量的作用域过大,导致生命周期过长

4、内部类持有外部类

5、hashmap中存放了某个对象,但是修改了这个对象中的参与计算哈希的值,这种情况如果再次去查找就找不到这个结果。导致无法删除该对象,导致内存溢出

6、缓存泄露,hashmapo中很容易遗忘,可以用弱引用,当内存不够时会进行垃圾回收WeakHashMap

 

 

 解决方案

1、尽量少在静态变量中进行new 对象,或者使用完将它们置为Null,这样GCroot的引用就会为空,垃圾回收机制就可以对其进行垃圾回收

2、明确内存对象的有效作用域,尽量缩小对象的作用域,能用局部变量处理的,就不要用成员变量,因为栈上局部变量会被自动回收

3、减少长声明周期对生命周期的引用。

4、使用StringBuilder和StringBuffer进行字符串连接,String和StringBuilder以及StringBuffer等都可以代表字符串,其中String字符串代表的是不可变字符串。

后了两者都是可变字符串,如果用多个String对象进行字符串连接运算,在运行期间可能会产生大量临时字符串。

5、各种连接(数据库连接,网络连接,IO连接操作),务必显示调用close关闭。

 

内存问题排查

第一步 首先确认逻辑问题

查看内存中对象的数量和大小,判断是否在合理的范围,调整JVM堆的大小,调整分代比例。

jmap -heap pid

jstatc 查看jvm内存状态

通过 jprofile进行本地分析,内存占有情况。