JAVA-内存泄露与溢出
除了程序计数器其余每个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进行本地分析,内存占有情况。