`
luzl
  • 浏览: 577773 次
  • 性别: Icon_minigender_1
  • 来自: 大连
社区版块
存档分类
最新评论

Final Finalize 和 垃圾回收的例子

    博客分类:
  • Java
阅读更多
final—修饰符(关键字)如果一个类被声明为final,意味着它不能再派生出新的子类,不能作为父类被继承。因此一个类不能既被声明为 abstract的,又被声明为final的。将变量或方法声明为final,可以保证它们在使用中不被改变。被声明为final的变量必须在声明时给定初值,而在以后的引用中只能读取,不可修改。被声明为final的方法也同样只能使用,不能重载。
finally—再异常处理时提供 finally 块来执行任何清除操作。如果抛出一个异常,那么相匹配的 catch 子句就会执行,然后控制就会进入 finally 块(如果有的话)。
finalize—方法名。Java 技术允许使用 finalize() 方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。这个方法是由垃圾收集器在确定这个对象没有被引用时对这个对象调用的。它是在 Object 类中定义的,因此所有的类都继承了它。子类覆盖 finalize() 方法以整理系统资源或者执行其他清理工作。finalize() 方法是在垃圾收集器删除对象之前对这个对象调用的。

我在thinking in java中看见以下一段代码。

//:Garbage.java
//Demonstration of the garbage
//collector and finalization

class Chair {
static boolean gcrun=false;
static boolean f=false;
static int created=0;
static int finalized=0;
int i;
Chair(){
i=++created;
if(created==47)
System.out.println("Created 47");
}
protected void finalize(){
if(!gcrun){
gcrun=true;
System.out.println(
"Beginning to finalize after"+created+
"Chairs have been created");
}
if(i==47){
System.out.println(
"Finalizing Chair #47,"+
"Setting flag to stop Chair creation");
f=true;
}
finalized++;
if(finalized>=created)
System.out.println(
"All"+finalized+"finalized");
}
}

public class Garbage{
public static void main(String[] args){
if(args.length==0){
System.out.println("Usage:\n"+
"java Garbage before\n or:\n"+
"java Garbage after");
return;
}
while(!Chair.f){
new Chair();
new String("To take up space");
}
System.out.println(
"After all chairs have been created:\n"+
"total created ="+Chair.created+
",total finalized ="+Chair.finalized);
if(args[0].equals("before")){
System.out.println("gc():");
System.gc();
System.out.println("runFinalization():");
System.runFinalization();
}
System.out.println("bye");
if(args[0].equals("after"))
System.runFinalizersOnExit(true);
}
}///:-

为什么执行java Gerbage before
以后,当所有对象创建完(比如8000个),这时只清除了2000个(不定)
应该只能创建47个对象啊


分析:
首先,在一个循环当中创建对象,并且只是创建,而不引用,也就是说这个对象会自动的被系统当作垃圾处理掉。但请注意,finalize()方法并不是立刻就会执行的,执行的时间完全由系统来决定。所以很有可能的情况是已经创建了20000个对象,才开始其中的某一个对象的清除工作(这可能和时间或者系统内容的占用有关)。看finalize()方法中的一段代码:
if (!gcrun) {
gcrun = true;
System.out.println(
"\nBeginning to finalize after" + created + "Chairs have been created\nat ");
}

就会出现这样的结果:
Beginning to finalize after 25038 Chairs have been created

这时对象的创建过程仍在继续(因为已经Finalize的对象还不满47个,Chair.f还是false)。所以Chair.created会继续增加。
直到有47个对象被清除了,Chair.f被置成true了,创建对象的循环才结束。看main方法中的一段代码:
System.out.println(
"\nAfter all chairs have been created:\n"
+ "total created ="
+ Chair.created
+ ",total finalized ="
+ Chair.finalized+"\n");

如上所说,Chair.created是不断增加的,而在这段代码执行之前,又会有N个对象被释放掉了,所以finalized也增加了。
结果可能是这样的:
total created =29096,total finalized =73

其实这一过程和你使用的JVM有很大关系,执行结果可能会很不相同。但有一点是可以肯定的,那就是我们无法确定JVM什么时候做对象的清除工作(这也是Thinking in java中这段代码的想要说明的),可能会在这个对象刚刚“无用”的时候就清除掉了,也可能滞后几秒,甚至永远不清除。

如果你的开发环境支持跟踪的话,你可以以STEP的方式运行,你会看到运行结果大不相同。给你看看我的运行结果:
Created 47
Beginning to finalize af
created
Finalizing Chair #47,Setting flag to stop Chair creation
After all chairs have been created:
total created =45993,total finalized =1800
gc():
runFinalization():
bye
All45993finalized

注意最后一行,因为人为的停顿,JVM有足够的时间将所有的对象都清除了。

结论:
不能指望finalize()方法能稳定的工作,尤其不能依靠它来做文件的关闭等操作,由于finalize()的不确定性,往往得不到你想要的结果。事实上我们只需要知道所有无用的对象,JVM会自己清除就够了。
分享到:
评论

相关推荐

    Java9以后的垃圾回收的具体用法

    相比于`finalize()`,`Cleaner`提供了更好的性能和确定性,因为它不会阻塞垃圾回收,且清理操作可以在独立的线程中异步执行。 以下是使用`Cleaner`的一个简单示例: ```java import java.lang.ref.Cleaner; import...

    东软春招java方向.pdf

    finalize是对象被垃圾回收前最后一次清理的机会。 13. 匿名内部类:可以继承其他类或实现接口,常用于简洁地定义回调或适配器。 14. 静态嵌套类(Static Nested Class)与内部类(Inner Class):静态嵌套类不持有对...

    java笔试试题用于应聘

    - **概念**: `finalize` 是 Java 中的一个特殊方法,通常用于对象被垃圾回收前进行必要的清理工作。 - **定义**: 它是 `Object` 类的一个方法,所有类都继承自 `Object`,因此都可以覆盖 `finalize()` 方法。 - *...

    百度2019年最新面试题库

    当对象即将被垃圾回收时,如果对象实现了`finalize()`方法,JVM会在回收之前调用该方法。需要注意的是,`finalize()`方法的调用是不确定的,并且可能只被调用一次。 #### 析构函数(finalization)的目的是什么 析构...

    Java 技术面试题

    10. **final, finally, finalize**:final 用于修饰变量、方法和类,表示不可变或不可重写;finally 是异常处理结构的一部分,确保代码块总会执行;finalize 是对象被垃圾回收前调用的方法,用来释放资源。 11. **...

    2018最新BAT java经典必考面试题最新版本.docx

    - **调用机制**:当一个对象即将被垃圾回收器回收时,`finalize` 方法会被自动调用。 - **重写**:开发者可以通过重写 `finalize` 方法来指定清理操作,但这并不是一种可靠的资源管理方式,因为 `finalize` 的调用...

    专题资料(2021-2022年)JAVA笔试题答案在最后.doc

    c) finalize是对象被垃圾收集器回收前进行清理操作的方法,但并不保证一定会被调用,不应依赖此方法进行资源清理。 d) finally与finalize不同,finally是异常处理的方法,而finalize是对象生命周期的一部分。答案...

    Java中的继承.docx

    在Java编程语言中,继承是...6. `finalize()`:在对象被垃圾回收之前调用的清理方法,但现在不推荐使用。 理解并熟练掌握这些Java继承相关的知识点,将有助于提升编程效率和代码质量,尤其是在构建大型软件系统时。

    java面试题

    - **描述**: `finalize` 是 Object 类中的一个方法,可以在对象被垃圾回收前执行清理工作。 - **作用**: - `finalize` 方法主要用于释放系统资源,如关闭数据库连接、释放图形设备等。 - 这个方法由垃圾回收机制...

    进销存系统文档作业例子

    finalize是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,可以覆盖此方法提供垃圾收集时的其他资源回收,例如关闭文件等。 13、sleep() 和 wait() 有什么区别? sleep是线程类(Thread)的...

    java代码性能的优化

    在这个例子中,如果对象`b`不再使用,但由于它是静态变量的一部分,所以不会被垃圾回收器清理。 #### 3. 限制new操作 频繁使用`new`关键字创建新对象会增加垃圾回收的压力,尤其是在循环中。应该尽量减少不必要的...

    Java笔试面试题详解

    finalize是对象被垃圾回收前调用的方法。 13. **Static Nested Class与Inner Class**:Static Nested Class是静态嵌套类,不持有对外部类的引用,可以直接实例化;Inner Class是非静态内部类,需要依附于外部类实例...

    JAVA数据库笔试题(答案在最后).doc

    当一个对象即将被垃圾回收器回收时,JVM 会自动调用该对象的 `finalize()` 方法,允许对象进行必要的清理工作。但是,该方法的调用不是强制性的,也不保证一定会被执行。 ### 4. Thread 类的使用 **题目示例:** `...

    java异常体系结构

    finalize方法则是Object类的一个方法,当一个对象不再有引用指向时,垃圾回收器会在回收对象前调用此方法,以便进行一些必要的清理工作。 最后,关于异常的继承,Java规定如果子类方法覆盖了父类的方法,那么它可以...

    技术面试题汇总

    - `finalize`: 已废弃的方法,曾经用于对象被垃圾回收前的清理工作。 **11. Overload和Override的区别。Overloaded的方法是否可以改变返回值的类型?** - **Overload**是在同一个类中通过方法名相同但参数列表不同的...

    JAVA程序员面试题1

    - **finalize方法**: 在对象被垃圾回收器回收前执行的清理方法,用于释放资源或执行必要的清理工作。 --- #### 四、& 和 && 的区别 **知识点1:& 的作用** - **位运算**: `&`是按位与运算符,用于对整型数据进行...

    java编码规范

    - **目的**:避免垃圾回收器无法回收资源。 - **反例**: ```java public class FM extends Applet { public void finalize() throws Throwable { beepButton.removeActionListener(act); // 违例 } ... } ...

    java对象类余接口的学习

    `finalize()`方法在对象被垃圾收集器回收前被调用,用于执行清理操作;`clone()`方法用于创建对象的一个副本;`getClass()`返回对象的运行时类。 13. **初始化块** 初始化块(构造器之外的代码块)在对象创建时...

    Java面试题大全(自己整理的最全的Java面试题,背过了很有用)

    `finalize` 方法是 `Object` 类中的一个方法,用于在对象被垃圾回收之前执行清理工作。然而,它的使用并不推荐,因为其行为无法预测且可能不会被调用。现代 Java 实践建议使用其他资源管理机制来替代 `finalize` ...

Global site tag (gtag.js) - Google Analytics