您的位置:首页 > 编程语言 > Java开发

Java的垃圾回收机制问题

2014-01-17 11:44 309 查看
----------------------
ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------
1.首先要明确两个概念,内存泄露(memory leak) 和 内存溢出(out of memory)
memory leak,程序创建对象分配空间使用后,没有释放相应的内存,多次循环后导致可用物理内存减少。
out of memory, 程序申请的内存大小超出了系统所能提供的内存大小。

内存泄露会导致内存溢出!

2.然后讲一讲垃圾回收机制(GC--garbage collection)
GC将自动回收本系统认为是垃圾的内存空间(堆空间)。
他的特点是:

1.垃圾收集是一种从无用对象收其所占用的内存,并使回收的内存能被再次使用的机制。 
2.无用对象是值它不能被程序中处于活动状态的部分引用(个人理解就是没有引用指向该对象时)。
3.垃圾回收机制(gc)处于低优先级的线程内,当使用内存较少时运行,但不能保证何时运行 
4.不可能强制运行垃圾回收线程,但是调用语句System.gc()有可能激活垃圾收集程序。 
5.在垃圾回收机制中无法保证对象被垃圾回收的顺序,也无法保证finalize()的方法被调用的顺序。
6.环形引用并不能阻止对象被回收

java中创建一个对象需要:在栈中创建一个引用变量,在堆中创建对象,引用变量指向对象。
当GC被调用时,他将按照栈中开始跟踪当发现没有被引用的空间时就释放。

一般来说内存泄漏有两种情况。一种情况如在C/C++语言中的,在堆中的分配的内存,在没有将其释放掉的时候,就将所有能访问这块内存的方式都删掉(如指针重新赋值);另一种情况则是在内存对象明明已经不需要的时候,还仍然保留着这块内存和它的访问方式(引用)。第一种情况,在Java中已经由于垃圾回收机制的引入,得到了很好的解决。所以,Java中的内存泄漏,主要指的是第二种情况。
下面举个小例子~

Vector v=new Vector(10);
for (int i=1;i<100; i++){
Object o=new Object();
v.add(o);
o=null;
}

该例子中引用变量o的值被手动赋值为null,也就是说coder主观上要释放其指向对象所站的空间。但事实上呢,当GC顺着栈查过来时,发现该内存在v引用变量所引用的内存中被引用了(链式引用)。。GC就放过了这块内存,于是乎内存泄露就产生了。

再举个更实际的例子:

public class FileSearch{

private byte[] content;
private File mFile;

public FileSearch(File file){
mFile = file;
}

public boolean hasString(String str){
int size = getFileSize(mFile);
content = new byte[size];
loadFile(mFile, content);

String s = new String(content);
return s.contains(str);
}
}

FileSearch类中有一个函数hasString,用来判断文档中是否含有指定的字符串,coder的本意是,根据文件名新建一个FileSearch对象,然后调用hasString方法,传入要查找的字符串,然后返回。
实际上呢,当调用hasString方法后,整片文章被导入到  成员变量content数组,由于content不是函数局部变量,在函数调完后并没有释放栈中的content引用变量,于是乎 就泄了(我指的是内存。。囧),当有人用该类编写的代码时,也没有释放FileSearch引用的话,多查几次之后就会拖慢整个系统。。。

很明显,这样的内存泄露都来自于代码逻辑层面,有良好的编码风格,考虑好变量的生命周期,那么会减少内存泄露产生的可能。
----------------------
ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: