繁体   English   中英

Java:在finalize方法上写入文件

Java: file write on finalize method

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

根据我的理解,单个对象只有在应用程序即将终止时才会销毁。 所以在C ++中我编写了一个Singleton类来记录我的应用程序,在Singleton logger的析构函数中,我记录了我的应用程序终止时的时间。 事情在C ++中完美运作。


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

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

Singleton记录器类:

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

有效的Java第2版:第7项:避免使用终结器

终结器是不可预测的,通常是危险的,并且通常是不必要的 它们的使用会导致不稳定的行为,性能不佳和可移植性问题。 终结器的有效用途很少,但根据经验,你应该避免使用终结器。

[...]声称保证最终确定的唯一方法是System.runFinalizersOnExit及其邪恶的双胞胎Runtime.runFinalizersOnExit 这些方法存在致命缺陷,已被弃用。

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

关闭挂钩是您创建的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 ,但有很多选择! 您将获得更稳定的代码,更少的调试工作,并可能更快的性能。 而且,他们不需要棘手的终结者行为。

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

相关问题
 
粤ICP备18138465号  © 2020-2022 STACKOOM.COM