Java garbage collection and finalization mechanism

以下内容摘自<<<<Java 2认证考试指南与试题解析>> 一书,更详细的内容请见

http://javaschool.learn.to


7.1 垃圾回收的概念

垃圾回收(Garbage-collection)是Java提供的一种自动内存回收功能,可以让程序员减轻许多内存管理的负担,也减少程序员犯错的机会。在Java程序的生命周期中,Java 运行环境提供了一个系统级的垃圾回收器线程,负责自动回收那些没有引用与之相连的对象所占的内存,这种内存回收的过程就叫垃圾回收。
在 Java 中,当你创建一个对象时,Java 虚拟机(JVM)会为该对象分配内存、调用该对象的构造方法并开始跟踪这个对象。当你停止使用一个对象(就是说,当没有对该对象有效的引用)时,JVM 通过垃圾回收器回收该对象所占用的内存。垃圾回收有两个好处:第一,它把程序员从复杂的内存追踪、监测、释放等工作中解放出来;第二,它防止了系统内存被非法释放,从而使系统更加稳定。

7.2 垃圾回收的特点

垃圾回收有以下三个特点:
1.只有当一个对象不被任何引用类型的变量引用时,它的内存才可能被垃圾回收器回收。
例如,以下代码当程序执行完第三行,字符串"Sample"对象依然被变量s2引用,因此不能被回收。当程序执行完第四行,变量s2引用了一个新的字符串对象,此时"Sample"对象不再被任何引用类型的变量引用,因此它的内存可以被垃圾回收器回收。
String s1="Sample";
String s2=s1;
s1=null;
s2=new String("Sample");
2.不能通过程序强迫垃圾回收立即执行。
垃圾回收器负责释放没有引用与之关连的对象所占用的内存,但是回收的时间对程序员是透明的,这就像每个居民只要把无用的垃圾袋(相当于无用的对象)放在指定的地方,清洁工人会来把它收拾走一样。但是,什么时候被收走,你是不知道的。垃圾回收器以独立的低优先级线程方式运行。在任何时候,你都不能通过程序强迫垃圾回收立即执行。你可以调用System.gc() 或者Runtime.gc()方法提示垃圾回收器进行内存回收操作,但是这也不能保证调用该方法后,垃圾回收线程立即执行。
3.当垃圾回收器将要释放无用对象的内存时,先调用该对象的finalize()方法。
在Object类中提供的finalize()方法是protected类型的,因此任何类都可以覆盖finalize()方法,在这个方法中进行对象所占相关资源的释放操作。例如,如果在某个类中曾打开了某个文件,可以在该类的finalize()方法中关闭该文件。
由于只有当垃圾回收器将要释放该对象的内存时,才会执行该对象的finalize()方法,如果在 Applet 或应用程序退出之前垃圾回收器始终没有执行释放内存的操作,因此垃圾回收器将不会调用无用对象的finalize()方法。另外,除非垃圾回收器认为你的 Applet 或应用程序需要额外的内存,否则它不会试图释放不再使用的对象的内存。换句话说,以下情况是完全可能的:一个 Applet 应用程序只占用了少量内存,没有造成严重的内存需求,于是垃圾回收器没有释放这些对象的内存就退出了。显然,如果你为某个对象定义了finalize() 方法,JVM 可能不会调用它,因为垃圾回收器不曾释放过这个对象的内存,调用System.gc() 也不会起作用,因为它仅仅是给 JVM 一个建议而不是命令。当一个对象将要退出生命周期时,可以通过finalize()方法来释放对象所占的其他相关资源,但是,JVM 有很大的可能不调用对象的finalize() 方法,因此很难保证使用该方法来释放资源是安全有效的。

7.3 考察要点

l 程序员无权回收内存。当一个对象没有被任何引用类型的变量引用时,该对象的内存可以被垃圾回收器自动回收;
2 垃圾回收器以独立的线程异步执行,回收的时间是程序无法预计的;
3 程序员可以调用System.gc()或者Runtime.gc(),提示垃圾回收器进行垃圾回收;
4 垃圾回收器进行垃圾回收时,调用对象的方法finalize。

7.4 试题解析

1.Consider the following piece of code.

1:String s = "abcd";
2:Integer x = new Integer(3);
3:String s2 = s + 4;
4:s2 = null;
5:s = null;

Following the execution of which line above, is the object referenced by s2 available for garbage collection.
a) Line 5
b) It is not possible to say when an object is available for garbage collection.
c) Line 4
d) The objects are not available until the executing thread is ended.
答案:c
解析:以上代码的第4行中,s2被赋值为空,此时,s2原来引用的对象"abcd4"不再被任何引用类型的变量引用,因此可以被垃圾回收器回收。注意:这里只是说可以被垃圾回收,而不是说在执行完这一行后立即进行垃圾回收。 2.What is the valid declaration for the finalize() method.
a) protected void finalize() throws Throwable
b) final finalize()
c) public final finalize()
d) private boolean finalize()
e) private final void finalize() throws Exception
答案:a
解析:finalize方法是在java.lang.Object类中定义的,它没有返回值,其访问类型为protected的。

3.You are concerned that your program may attempt to use more memory than is available. To avoid this situation you want to ensure that the Java Virtual Machine will run its garbage collection just before you start a complex routine. What can you do to be certain that garbage collection will run when you want .
a) You can not be certain when garbage collection will run
b) Use the Runtime.gc() method to force garbage collection
c) Ensure that all the variables you require to be garbage collected are set to null
d) Use the System.gc() method to force garbage collection
答案:a
解析:程序员是不能够指定垃圾回收器执行的时间的。方法Runtime.gc()只是提示垃圾回收器应该进行垃圾回收了,但是并不能够保证垃圾回收会立即进行。

4.Which statements describe guaranteed behavior of the garbage collection and finalization mechanisms?
a) Objects are deleted when they can no longer be accessed through any reference.
b) The finalize() method will eventually be called on every object.
c) The finalize() method will never be called more than once on an object.
d) An object will not be garbage collected as long as it is possible for an active part of the program to access it through a reference.
答案:c,d
解析:当对象不被任何引用类型的变量引用时,它就可以被垃圾回收器回收了。当垃圾回收器进行垃圾回收时,将调用对象的finalize方法。如果一个对象没有被垃圾回收,它的finalize方法是不会被调用的。因此,选项c和d正确。

5.Which is the earliest line in the following code after which the object created on the line marked (0) will be a candidate for being garbage collected, assuming no compiler optimizations are done?

public class Test{
static String f() {
String a = "hello";
String b = "bye"; // (0)
String c = b + "!"; // (a)
String d = b;
b = a; // (b)
d = a; // (c)
return c; // (d)
}
public static void main(String args[]) {
String msg = f();
System.out.println(msg); // (e)
}
}


a) The line marked (a).
b) The line marked (b).
c) The line marked (c).
d) The line marked (d).
e) The line marked (e).
答案:c
解析:在mark(0)的位置创建了一个新的字符串对象"bye",当没有任何引用类型的变量再引用对象"bye"时,才可以被垃圾回收。

你可能感兴趣的:(java,jvm,C++,c,C#)