java内存泄漏
- 静态集合类引起内存泄漏
/**
* @program: 个人demo
* @description: 内存泄露测试案例
* @author: Mr.Hu
* @create: 2019-03-17 20:55
*/
public class OOM {
static List<M_4> list=new ArrayList<>();
public static void main(String[] args) {
for (int i = 0; i < 10; i++) { //添加对象后,将引用变量赋值为空
M_4 o=new M_4();
list.add(o);
o=null;
}
for (M_4 o:list) {
System.out.println(o.i);
}
}
}
class M_4{ //单个内存为4M
int[] a=new int[1024*1024];
double i=Math.random();
}
输出:
0.33900138911994226
0.6552957195660072
0.056640088412603484
虽然引用变量被设置为null,但是那些对象还被集合引用着并且仍然可以使用。
要避免这种简单方法是集合赋值为null。
- 各种连接
比如数据库连接(dataSourse.getConnection()),网络连接(socket)和io连接,除非其显式的调用了其close() 方法将其连接关闭,否则是不会自动被GC 回收的。
这种情况下一般都会在try 里面去的连接,在finally里面释放连接。
- 单例模式中引用其它的对象
单例对象在初始化后将在 JVM 的整个生命周期中存在(以静态变量的方式实现的),如果单例对象持有外部的引用,那么这个对象将不能被 JVM 正常回收,导致内存泄漏
public class Single {
static int[] a=new int[1024*1024];
private static Single single=new Single(); //此处变量是static
private Single(){}
Single getInstance(){
return single;
}
}
总结:
这些东西不会被回收也是因为可达性分析算法,算法里面可以作为GCroot的对象有
- Java虚拟机栈(栈帧中的本地变量表)中引用的对象
- 方法区中类静态属性引用的对象(比如单例模式、静态集合等)
- 方法区中常量引用的对象
- 本地方法栈中native方法引用的对象
附录:可以被回收的情况
public class OOM {
public static void main(String[] args) {
M_4 m=new M_4();
M_4 m2=new M_4();
M_4 m3=new M_4();
m=null;m2=null;m3=null;
System.gc();
}
}
class M_4{ //单个内存为4M
int[] a=new int[1024*1024];
double i=Math.random();
}
Gc日志如下:
日志代码解读连接
[GC (System.gc()) [PSYoungGen: 6280K->728K(9216K)] 14472K->8928K(19456K), 0.0018907 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (System.gc()) [PSYoungGen: 728K->0K(9216K)] [ParOldGen: 8200K->654K(10240K)] 8928K->654K(19456K), [Metaspace: 3458K->3458K(1056768K)], 0.0068374 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
Heap
PSYoungGen total 9216K, used 82K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
eden space 8192K, 1% used [0x00000000ff600000,0x00000000ff614920,0x00000000ffe00000)
from space 1024K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x00000000fff00000)
to space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
ParOldGen total 10240K, used 654K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)
object space 10240K, 6% used [0x00000000fec00000,0x00000000feca3a38,0x00000000ff600000)
Metaspace used 3464K, capacity 4500K, committed 4864K, reserved 1056768K
class space used 377K, capacity 388K, committed 512K, reserved 1048576K
分析日志可以看出所有对象都被回收了!