代码改变世界

C#’s ~ vs Java’s finalize

  横刀天笑  阅读(1549)  评论(7编辑  收藏  举报

本文是上周写一个功能测试时,期望在测试结束时,利用Java的析构函数来关闭浏览器发现的问题,当然,这种方式是不建议采用的。因为我的背景是.NET开发,因此对Java的析构函数产生了误解。

作为一个C# Programer我们都知道,垃圾回收会帮我们回收托管资源,但那些非托管资源(比如文件句柄,数据库连接)垃圾回收是不会帮我们回收的,所以我们必须显式的回收这些资源。比如很多使用了非托管资源的类型都实现了Dispose方法,他们期望使用这些类型的开发人员能够显式的去调用这个方法来释放非托管资源,不过如果你没有显式调用那不就产生资源泄露了?别怕,还有最后的安全屏障:终结方法(不过终结方法会带来其他很多问题,这个在《CLR via C#》里有很详细的描述,本文关注点并不在此)。比如下面这段代码:

using System;
 
public class Wrapper
{
    public Wrapper()
    {
        Console.WriteLine("ctor");
    }
 
    ~Wrapper()
    {
        Console.WriteLine("finalize");
    }
}
 
public class Program
{
    private static Wrapper wrapper = null;
 
    public static void Main(String[] args)
    {
        wrapper = new Wrapper();
    }
}

上面的代码执行的结果会是:

ctor
finalize

C#的终结方法(析构函数,为了避免产生误解,微软后来改名了)在对象被垃圾回收或程序退出时会被调用。

再看看下面这段几乎一模一样的Java代码:

//Wrapper.java
public class Wrapper{
 
    public Wrapper(){
        System.out.println("ctor");
    }
    
    protected void finalize(){
        System.out.println("finalize");
    }
}
 
//Program.java
public class Program{
    private static Wrapper wrapper = null;
    
    public static void main(String[] args){
        wrapper = new Wrapper();
    }
}

输出的结果却是:

ctor

也就是析构函数并没有执行。

最后查文档得知,在JVM中如果该对象没有被垃圾回收则该对象的析构函数就不会调用。也就是说,如果你这个对象在JVM退出之前一直都没有被垃圾回收,那么默认情况下,你的析构函数是不会调用的,这也就带来了上面所说的结果。

也就是这一点让我这个.NET背景的程序员栽跟头了。

不过Java也提供了其他方式,让你确定在JVM退出时调用所有对象的析构函数,比如上面的代码只需要加一个System.runFinalizersOnExit(true),然后执行结果就和C#版本的一样了:

//Wrapper.java
public class Wrapper{
 
    public Wrapper(){
        System.out.println("ctor");
    }
    
    protected void finalize(){
        System.out.println("finalize");
    }
}
 
//Program.java
public class Program{
    private static Wrapper wrapper = null;
    
    public static void main(String[] args){
        System.runFinalizersOnExit(true);
        wrapper = new Wrapper();
    }
}

不过System.runFinzalizersOnExit是一个已不建议采用的方法了。

编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
点击右上角即可分享
微信分享提示