java - Mac OS Java 7 JDialog.dispose 内存泄漏

标签 java macos swing memory-leaks awt

我在调用 JDialog.dispose 来处理 JDialog 时观察到操作系统和 Java 版本之间存在一些不一致的行为(对于 JFrame 也会发生)。

下面的简单示例应用程序可用于演示该问题。如果您运行它并对应用程序进行概要分析,您会注意到通过单击“新建对话框”创建并随后关闭的任何 JDialog 实例都不会被垃圾收集,因为它们仍在被 sun.lwawt.macosx 的实例引用。 CPlatformWindow,导致应用程序内存泄漏。

我不认为这是由于任何弱引用造成的,因为我在经历过 OutOfMemoryError 的环境中观察到这个问题,所以我希望任何可以被垃圾收集的东西都会一直在那个时候。

问题出现在以下环境中:

  • Mac OS X 10.9:Java 1.7.0_5
  • Mac OS X 10.9:Java 1.7.0_45

该问题不会出现在以下环境中:

  • Mac OS X 10.9:Java 1.6.0_65
  • Windows 7:Java 1.7.0_45

在这些环境中,JDialog 实例被迅速收集并且(显然)在 JProfiler 中不再可见。

注意:问题发生在使用 DISPOSE_ON_CLOSE 或手动处理关闭时,如示例中注释掉的那样。

import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.*;

public class Testing extends JFrame {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                final JDialog parent = new JDialog((Frame)null, "Parent", false);

                JButton add = new JButton("New Dialog");
                add.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        final JDialog child = new JDialog(parent, "Child", false);
                        // child.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
                        child.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);                       
                        child.setSize(100, 100);

                        //child.addWindowListener(new WindowAdapter() {
                        //    @Override
                        //    public void windowClosing(WindowEvent e) {
                        //        child.setVisible(false);
                        //        child.dispose();
                        //    }
                        //});
                        child.setVisible(true);
                    }
                });

                parent.add(add);
                parent.pack();
                parent.setVisible(true);
            }
        });
    }
}

我做错了什么吗?

我的预期行为不正确吗?

如果没有,谁能给我指出一份涵盖此问题的 Java 错误报告(我没有找到一个)?

有任何建议的解决方法吗?

最佳答案

我看到了同样的事情,并且能够通过覆盖我窗口上的 dispose 方法来释放窗口,如下所示:

@SuppressWarnings("deprecation")
@Override
public void dispose()
{
    ComponentPeer peer = getPeer();

    super.dispose();

    if (null != peer)
    {
        try
        {
            Class<?> peerClass = Class.forName("sun.lwawt.LWComponentPeer");

            Field targetField = peerClass.getDeclaredField("target");
            targetField.setAccessible(true);
            targetField.set(peer, null);

            Field windowField = peer.getClass().getDeclaredField("platformWindow");
            windowField.setAccessible(true);
            Object platformWindow = windowField.get(peer);

            targetField = platformWindow.getClass().getDeclaredField("target");
            targetField.setAccessible(true);
            targetField.set(platformWindow, null);

            Field componentField = peerClass.getDeclaredField("platformComponent");
            componentField.setAccessible(true);
            Object platformComponent = componentField.get(peer);

            targetField = platformComponent.getClass().getDeclaredField("target");
            targetField.setAccessible(true);
            targetField.set(platformComponent, null);
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }
}

这并没有发布 CPlatformWindow 但总比没有好,应该对您有所帮助。

关于java - Mac OS Java 7 JDialog.dispose 内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19781877/

相关文章:

python - 命令行不使用 conda 环境中的 python,即使它处于事件状态,可能是 .bash_profile 中的问题?

java - 有人试过混合使用 JavaFX 和 JRuby 吗?

java - 当 JLabel 包含 HTML 时,BoxLayout 不遵守胶水

java - 在java中将字符串列表/集合转换为json对象

java - JMX 垃圾收集和 System.gc() 之间的区别?

macos - OS X 钥匙串(keychain)编程资源

java - OS X 上的 SWT : how to make trees and tables striped

java - Eclipse 的代码搜索功能如何工作?

java - 如何防止 Java Web Start 应用程序缓存额外的下载资源

java - 在现有的 Swing 项目中使用 JavaFX 的 MediaPlayer