繁体   English   中英

Java:在finalize方法上写入文件

Java: file write on finalize method

提示:本站收集StackOverFlow近2千万问答,支持中英文搜索,鼠标放在语句上弹窗显示对应的参考中文或英文, 本站还提供   中文繁体   英文版本   中英对照 版本,有任何建议请联系yoyou2525@163.com。

据我了解,单例对象仅在应用程序即将终止时才会销毁。 因此,在 C++ 中,我编写了一个 Singleton 类来记录我的应用程序,并在该 Singleton 记录器的析构函数中记录我的应用程序终止的时间。 事情在 C++ 中完美运行。


现在我想在 Java 中使用相同的记录器,因为在 Java 中没有析构函数,所以我为该单例记录器实现了 finalize 方法。 但似乎 finalize 方法实际上从未被调用过。 所以,我添加了System.runFinalizersOnExit(true); 行,在我的代码中的某处(尽管我知道它已被弃用),并且每次在应用程序终止之前都会调用 finalize 方法。 但是还是有问题! 如果我尝试在该 finalize 方法中写入任何文件,它不起作用,尽管 System.out 工作没有任何问题! :(

你们能帮我解决这个问题吗? 这是我尝试做的示例代码:

单例记录器类:

public class MyLogger {
    FileWriter writer;
    private MyLogger() {
        try {
            this.writer = new FileWriter("log.txt");
        }
        catch (IOException ex) {
        }
    }

    public static MyLogger getInstance() {
        return MyLoggerHolder.INSTANCE;
    }

    private static class MyLoggerHolder {
        private static final MyLogger INSTANCE = new MyLogger();
    }

    @Override
    protected void finalize () {
        try {
            super.finalize();
            System.out.println("Here"); //worked correctly.
            this.writer.write(new Date().toString()+System.getProperty("line.separator"));
            this.writer.write("End");
            this.writer.flush(); //does not work!
            this.writer.close();
        }
        catch (Throwable ex) {
        }
    }
    public synchronized void log(String str) {
        try {
            this.writer.write(new Date().toString()+System.getProperty("line.separator"));
            this.writer.write(str+"\n");
            this.writer.flush();
        }
        catch (IOException ex) {
        }
    }
 }

主要的:

public class Main {
    public static void main(String[] args) {
        System.runFinalizersOnExit(true);
        MyLogger logger = MyLogger.getInstance();
        logger.log("test");
    }
}
6 个回复

这是那些奇怪的问题之一。 注意:我不会编写自己的 Logging 类 - 看看 log4j 什么的......

如前所述,我真的不会真正使用 finalize。

...

根据您的说法,您的目标只是在程序停止时运行某些东西。

我会注册一个shutdownhook ...

shutdownhook 是一个用户定义的对象,它扩展了 Thread 类。 例如,您可以在记录器中定义一个静态内部类

这是一个例子:

http://www.crazysquirrel.com/computing/java/basics/java-shutdown-hooks.jspx

这是 API 文档:http: //java.sun.com/j2se/1.4.2/docs/api/java/lang/Runtime.html#addShutdownHook%28java.lang.Thread%29

Effective Java 第 2 版:第 7 项:避免使用终结器

终结器是不可预测的,通常是危险的,而且通常是不必要的。 它们的使用会导致行为不稳定、性能不佳和可移植性问题。 终结器几乎没有有效用途,[...] 但根据经验,您应该避免使用终结器。

[...] 唯一声称可以保证终结的方法是System.runFinalizersOnExit及其邪恶的孪生兄弟Runtime.runFinalizersOnExit 这些方法存在致命缺陷,已被弃用。

正如其他答案所说,使用 finalize 被认为是不好的做法。 虚拟机关闭时发生某些事情的“官方”方法是使用关闭挂钩

关闭挂钩是您创建但不启动的 Thread 对象。 您使用Runtime.getRuntime().addShutdownHook(Thread)注册它,它将在 VM 关闭时调用。

Josh Bloch 在他的《Effective Java》一书中写道,在终结器中做任何事情都是不好的做法。

您可以选择在关闭应用程序时手动执行此操作:

  • 如果您关闭它(使用System.exit(0) ),请在那里调用该代码
  • 如果用户关闭它,添加一个监听器并在那里调用它。

除了使用 finalize 是不安全的这一事实(因为我确信您已经看到了这一点,因为您使用 System.runFinalizersOnExit 的方法已被弃用)您的 finalize 方法可能会引发异常/错误。 在这种情况下,您的异常/错误在您的 catch 语句中被捕获,并且没有对其进行任何处理。 更好的方法是:

try{
   System.out.println("Here"); //worked correctly.
   this.writer.write(new Date().toString()+System.getProperty("line.separator"));
   this.writer.write("End");
   this.writer.flush(); //does not work!
   this.writer.close();
}
catch(Throwable e){
   //Log or handle the issue
}
finally{
   super.finalize();
}

话虽如此,在 Java 中使用 finalize 通常不是一个好习惯,应该避免。

我建议您不要尝试推出自己的日志框架,而是查看许多预先存在的 Java 日志框架之一。 我使用log4j ,但有很多选择! 您将获得更稳定的代码、更少的调试工作以及可能更快的性能。 而且,它们不需要棘手的终结器行为。

1 相当于java finalize方法

在Go中有没有像java finalize这样的方法? 如果我有一个类型的结构 如何确保在对象被垃圾回收时,文件已关闭? ...

2011-01-08 23:40:19 2 1071   go
2 Java中的finalize方法

可能重复: 为什么java.lang.Object中的finalize()方法受到“保护”? finalize方法是用受保护的范围定义的,然后如何使诸如垃圾收集器之类的其他对象能够调用它。 ...

3 java finalize方法的使用

我的系统遭受内存泄漏的困扰,我尝试通过尽快释放内存来对其进行优化。 这是finalize方法的好用法吗? 我在哪里可以捕捉到“ Throwable”对象? } } ...

5 Java Finalize方法没有调用[重复]

这个问题在这里已有答案: 为什么最终没有被召唤? 4个答案 如何确保finalize()始终被调用(Thinking in Java exercise) 5个答案 这是一段代码。 finalize()方法应该在System.gc()命令之后调用,但不是 ...

6 可以在Java中重载finalize()方法

我已经读过某个方法,每个方法都可以重载。 完成() 当然是一种方法。 但在搜索时我也发现你不能重载这个方法。 所以问题是我们可以重载finalize()方法吗? 如果是,那么它是如何实施的? ...

7 Java中的finalize方法的问题

这个问题已经在这里有了答案: 什么时候在Java中调用finalize()方法? 16个答案 在上一次练习中,我对finalize方法遇到了问题。 好像我有一个过时的方法,而且我似乎找不到finalize的最新版本。 我有两个文件,需要调用“ finalize ...

8 Java面试题:finalize()方法

在一次采访中,我得到了以下短语: 对象的 finalize() 方法的调用是对象被垃圾回收之前发生的最后一件事。 我不得不回答: 真的 错误的 我选择了True但这是错误的。 你能解释一下为什么吗? ...

10 关于Java敲定方法的面试题

我遇到了困难的(对我来说)Java 关于最终确定方法的面试问题。 假设你已经给出了 finalize 方法,如下所示: 现在给出下面的 object 场景。 你将如何解决这个问题? 如果 A 没有引用 B,那么这个问题可能会更容易,因为 GC 将运行,它将收集 B 并为 B 调用 finalize, ...

2011-05-03 01:40:36 4 1553   java
暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2022 STACKOOM.COM