Java有析构函数吗?我好像找不到任何关于这个的文件。如果没有,我怎样才能达到同样的效果?

为了使我的问题更具体,我正在编写一个处理数据的应用程序,规范说应该有一个“重置”按钮,使应用程序恢复到最初的启动状态。但是,除非应用程序关闭或按下重置按钮,否则所有数据必须是“活的”。

作为一个通常的C/ c++程序员,我认为这是微不足道的实现。(因此我打算最后实现它。)我构造了我的程序,使所有“可重置”的对象都在同一个类中,这样当按下重置按钮时,我就可以销毁所有“活动”对象。

我在想,如果我所做的只是解除对数据的引用,并等待垃圾收集器收集它们,如果我的用户重复输入数据并按下重置按钮,是否会出现内存泄漏?我还在想,既然Java作为一种语言相当成熟,应该有一种方法来防止这种情况发生或优雅地解决这个问题。


当前回答

这里有很多很好的答案,但还有一些关于为什么应该避免使用finalize()的额外信息。

如果JVM由于System.exit()或Runtime.getRuntime().exit()而退出,终止器将不会默认运行。From Javadoc for Runtime.exit():

虚拟机的关闭顺序由两个阶段组成。在第一阶段,所有已注册的shutdown钩子(如果有的话)将以某种未指定的顺序启动,并允许并发运行,直到它们完成。在第二阶段中,如果启用了退出时终止,则运行所有未调用的终结器。完成此操作后,虚拟机将停止。

您可以调用System.runFinalization(),但它只会“尽最大努力完成所有未完成的终结”——并不能保证。

有一个System.runFinalizersOnExit()方法,但不要使用它——它是不安全的,很久以前就已经弃用了。

其他回答

也许你可以试试……Finally块来最终确定您正在使用对象的控制流中的对象。当然,它不会自动发生,但在c++中破坏也不会发生。你经常在finally块中看到资源的关闭。

应该避免使用finalize()方法。它们不是一种可靠的资源清理机制,滥用它们可能会在垃圾收集器中引起问题。

如果你在对象中需要一个释放调用,比如释放资源,使用显式的方法调用。这个约定可以在现有的api中看到(例如Closeable, Graphics.dispose(), Widget.dispose()),通常通过try/finally调用。

Resource r = new Resource();
try {
    //work
} finally {
    r.dispose();
}

尝试使用已处理对象应该抛出运行时异常(参见IllegalStateException)。


编辑:

我在想,如果我所做的只是 来解除对数据的引用并等待 垃圾收集器来收集它们, 会不会有内存泄漏,如果我的 用户反复输入数据和 按了重置键?

一般来说,您所需要做的就是取消对对象的引用——至少,这是它应该工作的方式。如果您担心垃圾收集,请查看Java SE 6 HotSpot[tm]虚拟机垃圾收集调优(或您的JVM版本的等效文档)。

不,. lang。Object#finalize是最接近的。

但是,不保证何时(以及是否)调用它。 看到:java.lang.Runtime # runFinalizersOnExit(布尔)

我同意大部分答案。

你不应该完全依赖finalize或ShutdownHook

完成

The JVM does not guarantee when this finalize() method will be invoked. finalize() gets called only once by GC thread. If an object revives itself from finalizing method, then finalize will not be called again. In your application, you may have some live objects, on which garbage collection is never invoked. Any Exception that is thrown by the finalizing method is ignored by the GC thread System.runFinalization(true) and Runtime.getRuntime().runFinalization(true) methods increase the probability of invoking finalize() method but now these two methods have been deprecated. These methods are very dangerous due to lack of thread safety and possible deadlock creation.

shutdownHooks

public void addShutdownHook(Thread hook)

注册一个新的虚拟机关闭钩子。

Java虚拟机在响应两种事件时关闭:

The program exits normally, when the last non-daemon thread exits or when the exit (equivalently, System.exit) method is invoked, or The virtual machine is terminated in response to a user interrupt, such as typing ^C, or a system-wide event, such as user logoff or system shutdown. A shutdown hook is simply an initialized but non-started thread. When the virtual machine begins its shutdown sequence it will start all registered shutdown hooks in some unspecified order and let them run concurrently. When all the hooks have finished it will then run all uninvoked finalizers if finalization-on-exit has been enabled. Finally, the virtual machine will halt. Note that daemon threads will continue to run during the shutdown sequence, as will non-daemon threads if the shutdown was initiated by invoking the exit method. Shutdown hooks should also finish their work quickly. When a program invokes exit the expectation is that the virtual machine will promptly shut down and exit. But even Oracle documentation quoted that

在极少数情况下,虚拟机可能会中止,即停止运行而不完全关闭

这发生在虚拟机从外部终止时,例如在Unix上使用SIGKILL信号或在Microsoft Windows上使用TerminateProcess调用。如果本机方法出错,虚拟机也可能中止,例如破坏内部数据结构或试图访问不存在的内存。如果虚拟机中止,则不能保证是否会运行任何shutdown钩子。

结论:合理使用try{} catch{} finally{}块,释放finally(}块中的关键资源。在finally{}块中释放资源时,捕获Exception和Throwable。

finalize()函数是析构函数。

但是,通常不应该使用它,因为它是在GC之后调用的,并且您无法判断何时会发生(如果有的话)。

而且,释放具有finalize()的对象需要多个GC。

您应该尝试使用try{…清理代码中的逻辑位置。最后}{…}语句!