JVM内存泄露与内存溢出
一、内存泄露
1、内存泄露是指程序动态分配了内存,但在程序结束时没有释放这部分内存,从而造成那部分内存不可用的情况,重启程序或者计算机即可解决。内存泄露是由软件设计缺陷引起的。
2、Java中当被分配的对象可达但已无用(未对不再使用内存单元的引用置null,导致GC不能完成对其回收)即会引起。
如下代码:
public void methodA(){
for(int i=0;i<100;i++){
Object obj = new Object();
//使用这个obj
MethodB(obj);
//......
obj = null;
}
}
public void MethodB(Object obj){
XXX.list.add(obj);
/todo......
}
上面的第一个方法创建100个对象,将每个对象传递给第二个方法,然后将对象引用置null,假设第二个方法的XXX.list这个集合忘记设置为null(或者list是一个全局静态属性),那么将会造成这100个对象说占用的内存永远无法被GC收集,这就是一种内存泄露.
3、Java的内存泄露与C++的内存泄露区别
在Java中,内存泄露就是存在一些被分配的对象,这些对象具备以下特征无法被GC回收,将一直占用内存直到进程被关闭:
特点一:这些对象是可达的,即在有向图中,存在通路可以与其相连
特点二:这些对象对程序来说已经是无用的了,即程序以后不会再使用这些对象。
在C++中,内存泄露的范围更大一些,包含两种情况:
情况一:类似于Java,对象对程序来说已经无用,程序以后不再使用这些对象呢,但对象是可达的,因此对象占用的内存却没有释放。
情况二:这种情况更多,对象对程序来说已经无用,对象又是不可达的,由于C++中没有GC,对象占用的内存永远不能得到回收。在Java中,这些不可达的对象都由GC负责回收,因此程序员不需要考虑这部分内存的泄露,C++内存泄露如下:
typedef struct {
int price;
char* title;
} Book;
int main()
{
int i=0;
while(i++<100)
{
//分配Book结构内存后没有主动释放内存,导致内存泄露
Book *pBook = new Book;
}
return 0;
}
小结:对于C++,程序员需要自己控制内存的申请和释放,而对于Java只需要管理内存的申请,不需要管理释放(只需保证对象不可达即可)。通过这种方式Java提高了编程效率。也提高了程序的健壮性。故Java中是存在内存泄露的,但范围比C++要小。
二、内存溢出
1、内存泄露是导致内存溢出的原因之一;内存泄露积累起来讲导致内存溢出。内存泄露可以通过完善代码来避免;内存溢出可以通过调整配置来减少发生频率,单无法彻底避免。
2、Java内存溢出类型:
永久代内存溢出:java.lang.OutOfMemoryError:PermGen Space
堆内存溢出:java.lang.OutOfMemoryError:Java Heap space
虚拟机栈和本地方法栈内存溢出:StackOverflowError
本机直接内存溢出:
以上每种溢出类型在后面“JVM内存溢出与排错”中详解。