当前位置: 首页 > 面试题库 >

JVM / GC是否在程序/线程出口上调用`finalize()`?

邵君植
2023-03-14
问题内容

PS:我确实知道如何正确清理,而无需依赖finalize()

Java是否不能保证在程序退出时会进行正确的垃圾回收?

例如,可以说我将一些数据保留在缓存中,而不是经常对其进行序列化,我还实现finalize()了这样一个希望:如果由于某种原因(崩溃除外),我的程序正常退出,那么缓存将被写入数据库/文件/一些-
由我的代码存储在finalize()方法中。但是根据下面的小实验,看来JVM似乎没有“优雅地”清理内存,而是退出了。

Java规范(请参阅程序出口)说没有什么关于出口时如何处理内存/
gc的信息。还是应该一直在查看规范的其他部分?

在Windows 7上,使用以下示例(末尾输出)使用1.6.0.27 64位

public class Main {

        // just so GC might feel there is something to free..
    private int[] intarr = new int[10000];

    public static void main(String[] args) {
        System.out.println("entry");
        Main m = new Main();
        m.foo();
        m = new Main();
        // System.gc();
        m.foo();
        m = null;
        // System.gc();
        System.out.println("before System.exit(0);");
        System.exit(0);
    }

    @Override
    protected void finalize() throws Throwable {
        System.out.println("finalize()");
        super.finalize();
    }

    public void foo() { System.out.println("foo()"); }
}

/*
 * Prints:
 * entry 
 * foo() 
 * foo() 
 * before System.exit(0);
 */

变化:

  • 如果我取消注释任何人,System.gc()则否finalize()
  • 如果我都取消注释,System.gc()那么将finalize()被调用两次。
  • 是否System.exit()被调用对是否finalize()被调用没有影响。

问题答案:

不,Java不保证在程序退出时GC将触发。如果要对退出使用Runtime.addShutdownHook方法执行操作。阅读这在SPEC说什么孙文章。

Java平台的规范几乎没有保证垃圾收集的实际工作方式。这是Java虚拟机规范(JVMS)关于内存管理的内容。

堆是在虚拟机启动时创建的。自动存储管理系统(称为垃圾收集器)可以回收对象的堆存储;对象永远不会显式释放。Java虚拟机不假定使用特定类型的自动存储管理系统,可以根据实现者的系统要求选择存储管理技术。1尽管看起来有些混乱,但未严格定义垃圾收集模型这一事实实际上很重要有用-
严格定义的垃圾回收模型可能无法在所有平台上实现。同样,从长远来看,这可能会阻止有用的优化并损害平台的性能。

尽管没有一个地方包含所需垃圾收集器行为的完整定义,但是许多Java模型是通过Java语言规范和JVMS中的许多部分隐式指定的。虽然不能保证遵循的确切过程,但是所有兼容的虚拟机都共享本章中介绍的基本对象生命周期。



 类似资料:
  • 问题内容: 在阅读了这样的问题之后,我有了一些疑问。请帮助理解。 调度涉及确定何时运行流程以及运行时间的多少。 linux内核是否调度线程或进程?由于内核中的进程和线程没有区别,调度程序如何对待它们? 如何确定每个线程的数量?一个。如果为一个进程确定了一个时间量(例如100us),是在该进程的所有线程之间共享该时间吗?或b。每个线程的数量由调度程序决定吗? 注意:问题1和问题2是相关的,可能看起来

  • 根据文件:https://docs.python.org/3/library/threading.html 线程可以标记为“守护线程”。此标志的意义在于,当只剩下守护进程线程时,整个Python程序将退出。初始值从创建线程继承。可以通过daemon属性或daemon构造函数参数设置该标志。 示例代码: 参考许多其他StackOverflow答案,我不清楚当主线程调用时,守护线程是否被迫关闭

  • 问题内容: 我决定使自己熟悉node.js,并阅读有关该主题的几篇文章。我仍然不清楚的是,当您调用node.js函数时,node.js是否在线程池中创建新线程和/或在线程上调度任务。 例如,如果我调用它是否在其他线程上执行? 如果是,[如何]我可以编写自己的函数或在其他线程上运行? 问题答案: 没有用于文件操作的异步API,因此node.js为此使用了线程池。您可以在libuv的代码中看到它。 该

  • 代码: 有人能解释为什么它崩溃后分离和如何解决这个问题吗?

  • Win32程序通常有一个消息循环,循环调用GetMessage或PeekMessage,然后调用DispatchMessage将消息分派到相关窗口的窗口进程。 但是,真的有必要这样做吗?我是否可以直接在消息循环中查看 MSG 对象,并在其中执行所需的操作,而无需调用 DispatchMessage?我说的是我有一个窗口没有其他窗口控件的情况,例如,如果该窗口仅用作direct3d显示窗口,则消息将

  • 对于Java 8之后的JVM 当metaspace的大小