java - 为什么 JFrame 对象似乎保持 Activity 状态,即使没有对它的引用?

标签 java garbage-collection jvm

如果我没记错的话,在Java中可以这样写

new JFrame();

不保存JFrame任何变量中的引用。该程序将在屏幕上显示一个 GUI 窗口并使其保持打开状态,直到程序关闭。 (如果这个前提是错误的,请纠正我)。

理论上,我们可以认为自从 JFrame现在用户代码无法访问该对象,GC 应在某个时刻释放该对象。因此,相关的操作系统资源(GUI 窗口等)也将被释放。

但是,如果我的理解是正确的 - 该程序是一个有效且可运行的 Java 程序(尽管是一个非常无用的程序),并且它在任何时候都不会崩溃或以奇怪的方式运行(如果这个前提是错误的,请再次纠正我) )。

看来GC不会收集JFrame即使没有任何对它的引用,或者至少它不会导致关联的操作系统资源被释放。

我想了解:这怎么可能?

  1. JFrame 的构造函数是否保存this为了不被收集到任何地方?在 source code for JFrame 's superclass java.awt.Frame (方法 noteFrame )该帧似乎保存在弱引用队列中。但由于这些是弱引用,这似乎无法解释事情

  2. 事实上GC确实最终释放了JFrame - 然而, JFrame 的终结器方法释放关联的操作系统资源,因此 GUI 窗口保持打开状态?

  3. 还有其他解释吗?

请注意,这是更多 theoretical question I posted on SE.SE 的后续问题。这个问题有所不同,因为它具体涉及 Java 实现细节。

最佳答案

仅通过 new JFrame() 创建且没有任何其他操作的 JFrame 将不会在屏幕上打开,也不会阻止垃圾回收。只有连接到显示设备的框架才会从 AWT 实现中引用,并且在显式断开连接之前无法进行垃圾收集。

可以使用以下代码验证:

public static void main(String[] args) {
    check(new JFrame(), "just creating a JFrame", x -> {});
    check(new JFrame(), "creating and connecting a JFrame", JFrame::pack);
    check(Frame.getFrames()[0], "calling dispose()", Frame::dispose);
}
private static <T> void check(T obj, String description, Consumer<T> action) {
    System.out.println(description);
    action.accept(obj);
    WeakReference<T> r = new WeakReference<>(obj);
    obj = null;
    System.gc();
    if(r.get() == null) System.out.println("collected immediately");
    else {
        System.runFinalization();
        System.gc();
        if(r.get() == null) System.out.println("collected after finalization");
        else System.out.println("still alive");
    }
}

将打印

just creating a JFrame
collected immediately
creating and connecting a JFrame
still alive
calling dispose()
collected after finalization

在典型的实现中。

值得注意的是,从未连接到显示设备的框架会像普通对象一样立即被收集,而通过 dispose() 调用连接并随后断开连接的框架则需要清理操作,在第一次垃圾收集器运行后发生。

此外,该示例使用 pack() 而不是 setVisible(true) 来演示框架可以在不可见的情况下连接到显示设备。这使得 isDisplayable() 之间存在差异。它反射(reflect)组件是否连接到屏幕设备和 isVisible()它告诉 visible 属性是否已设置为 true。最后,组件仅报告 isShowing()当它可见且可显示并且其所有父级都显示时,为 true

关于java - 为什么 JFrame 对象似乎保持 Activity 状态,即使没有对它的引用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60994544/

相关文章:

java - 如何上传图片并将其保存在数据库中?

java - 模拟器上的背景被拉伸(stretch)

garbage-collection - 类型安全与垃圾回收实用性的关系

java - 如果只有完全限定名称,如何获取 java 类的二进制名称?

java - 您使用 ARM Jazelle 的体验如何?

java - Jmap 错误 "More than one non-option argument"

java - 用于将现有PDF转换为PDF/A的免费Java库

java - 将特定行和列的 .csv 转换为 .xls 值加倍

c# - 在 C# 早期使用 float 大括号释放变量

java - 我的 JAVA_OPTS 设置没问题吗?