SCJP复习指南3

为什么想收集垃圾

你可能是一位经验非常丰富的Java程序员,但是你未必想过弄清楚垃圾收集的来龙去脉。的确垃圾收集在Java程序中有点奇怪。本章中垃圾收集是指释放前面分配的内存,这些内存不会再被程序继续使用。当内存已经变得没用的时候,我们把它们叫做垃圾,它们的存在还会使得其他可用内存空间变得混乱。

Java语言设计的非常出色,其中之一就是你不用担心垃圾收集。C/C++程序员必须要手动分配和释放内存,这会导致一个问题出现就是“内存泄露”。有些版本的Windows程序,比如WordExcel,可能几次简单的打开和关闭应用程序就会引起某些问题出现。有时候内存泄露可能最终导致系统死机,你不得不重新启动电脑。在成千上万的C/C++代码中,程序员很可能分配一块内存却忘记释放它。

Java和垃圾

C/C++不同,Java语 言会自动释放不再使用的引用。你不用从成千上万代码中苦苦查找不会再使用的内存。你也不需要知道如何分配合适大小的空间给不同的数据类型,以确保程序的兼 容性。因此,看起来你没有必要知道垃圾收集的细节知识。有一种情况例外,就是你想通过考试或者想了解垃圾收集的真实情况。

如果你编写程序过程中需要创建大量的对象和变量,这时候如果知道引用什么时候会被释放是非常重要的。你需要知道自动垃圾收集的工作原理,你可以建议或者鼓励虚拟机进行垃圾收集,但是记住你不能强迫它作这个工作。

finalize

Java语言保证一个对象的finalize方法在对象被回收之前会调用。与其他类似垃圾回收的行为不同的是,这里是“保证”。但是finalize方法到底做什么呢?

乍一看,finalization像是C/C++语言中的析构器,在对象销毁之前清理其资源。不同的是Java语言不需要释放资源,因为垃圾回收器会处理内存分配。但是如果你引用了其他外部资源,比如文件信息,那么就有必要在finalization中释放资源了,这也是在JDK 1.4里面提出的参考。

当垃圾收集器判断出已经没有引用指向这个对象的时候,垃圾收集器就会调用对象的finalize方法。

因为垃圾收集器回收垃圾的行为是不确定的,你不知道什么时候他们会执行来收集垃圾。因此你也就没有办法知道什么时候finalize方法会被调用。但是,你一定想知道考试对垃圾回收这部分的要求,我们往下看。

垃圾收集的确是一个考点陷阱,因为你没有明显的方法来决定什么时候垃圾收集可用。因此你不能编写下面的代码:

if(EligibleForGC(Object){ //Not real code

System.out.print("Ready for Garbage");

}


正因为如此,你必须掌握下面的原则。

一旦一个对象不被其他任何对象引用的时候,它就变成可回收的对象了。你可以使用System.gc()来建议垃圾回收器收集垃圾,但是这并不能保证执行。

在方法中声明的本地变量在方法退出的时候就无效了,这个时候方法中的本地变量就成为了可回收的,方法每次执行的时候本地变量都会被重新创建。

无法访问

当代码已经无法再访问对象的时候,这个对象就成为了可垃圾回收的。有两种情况下会出现对象无法再被访问,第一,对象的引用设置为null;第二,指向这个对象的引用指向了其他的对象。有这样一种考试题目,在代码的某个部分把引用设置为null,你必须找出在哪里对象成为了可垃圾回收的。这种类型的题目比较简单。但是另外一种情况就不是这么明显了,我们看看下面的代码例子。

class Base{

String s;

Base(String s){

this.s = s;

}

public void setString(String s){

this.s = s;

}

}

public class UnReach{

public static void main(String argv[]){

UnReach ur = new UnReach();

ur.go();

}

public void go(){

Base b1 = new Base("One");

b1.setString("");

Base b2 = new Base("Two");

b1 = b2;


}

什么时候b1成为可垃圾回收的呢?假设你不被b1设置为空字符串所影响,那么你就可以判断出当b1指向b2的时候,原来的b1成为可垃圾回收的了。

课后测试题

问题1)下面哪段代码可以建议虚拟机执行垃圾收集?

1) System.free();
2) System.setGarbageCollection();
3) System.out.gc();
4) System.gc();

问题2) 在下面的代码片断中插入一行代码确保Integer对象被垃圾收集器回收。

public class Rub{

Integer i= new Integer(1);

Integer j=new Integer(2);

Integer k=new Integer(3);

public static void main(String argv[]){

Rub r = new Rub();

r.amethod();

}


public void amethod(){

System.out.println(i);

System.out.println(j);

System.out.println(k);

}

}

1) System.gc();

2) System.free();

3) Set the value of each int to null

4) None of the above


问题3)下面那句话是正确的?

1)You cannot be certain at what point Garbage collection will occur

2) Once an object is unreachable it will be garbage collected

3) Both references and primitives are subject to garbage collection.

3) Garbage collection ensures programs will never run out of memory


问题4)在哪里第8行创建的sb对象成为可垃圾回收的?

public class RJMould{

StringBuffer sb;

public static void main(String argv[]){

RJMould rjm = new RJMould();

rjm.kansas();

}

public void kansas(){

sb = new StringBuffer("Manchester");

StringBuffer sb2 = sb;

StringBuffer sb3 = new StringBuffer("Chester");

sb=sb3;

sb3=null;

sb2=null;

}

}

1) Line 11
2) Line 9
3) Line 12
4) Line 13

答案

答案1

4) System.gc();


答案2

4) None of the above 你只能建议垃圾回收器运行,但是无法决定他会在代码的哪个部分执行。注意只有对象的实例才可能成为垃圾回收对象,原始数据类型不会。


答案3

1) You cannot be certain at what point Garbage collection will occur

一旦一个对象不能在被访问,那么他将成为可垃圾回收的。但是你不能确定它什么时候会被回收。垃圾回收机制只对对象有效,对原始类型无效。你应该知道垃圾收集不能确保程序不会出现内存不足的情况。但是他能保证不再被使用的内存可以成为可用的。


答案4

4) Line 13

9行创建的sb2指向了第8行创建的对象,直到它成为不可到达的对象的时候,sb才成为可垃圾回收的。


答案5

1) finalize will always run before an object is garbage collected

对象在垃圾回收之前,它的finalize方法会被调用。Finalize方法不能在对象被回收后调用,因为那时候对象已经不存在了。当一个对象不能访问的时候,他就成为了可垃圾回收的,但是你无法保证它什么时候会被回收。选项4java中是不正确的,在C++中正确。

 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

光义

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值