我有一个需要打开多个JFrames的应用程序(这是一个日志查看器,有时你需要看到一堆原木在单独的窗口进行比较)。
看来,JVM(Java的8更新101在OS X)被保持的强引用到JFrame,这是防止它被垃圾收集,并最终导致一个OutOfMemoryError被抛出。
要看到问题,有200兆最大堆大小运行这个问题。 每打开一个窗口时,它消耗的内存50兆字节。 打开三个窗口(使用的RAM 150兆字节)。 然后关闭三个窗口(这调用Dispose),它应该释放内存。 然后尝试打开第四个窗口。 一个OutOfMemoryError被抛出和第四窗口不会打开。
我见过其他的答案,说明内存会自动释放必要的时候,以避免用完,但是这似乎并没有发生。
package com.prosc.swing;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.NumberFormat;
public class WindowLeakTest {
public static void main(String[] args) {
EventQueue.invokeLater( new Runnable() {
public void run() {
JFrame launcherWindow = new JFrame( "Launcher window" );
JButton launcherButton = new JButton( "Open new JFrame" );
launcherButton.addActionListener( new ActionListener() {
public void actionPerformed( ActionEvent e ) {
JFrame subFrame = new JFrame( "Sub frame" ) {
private byte[] bigMemoryChunk = new byte[ 50 * 1024 * 1024 ]; //50 megabytes of memory
protected void finalize() throws Throwable {
System.out.println("Finalizing window (Never called until after OutOfMemory is thrown)");
super.finalize();
}
};
subFrame.setDefaultCloseOperation( WindowConstants.DISPOSE_ON_CLOSE );
subFrame.add( new JLabel( "Nothing to see here" ) );
subFrame.pack();
subFrame.setVisible( true );
System.out.println( "Memory usage after new window: " + getMemoryInfo() );
}
} );
launcherWindow.add( launcherButton );
launcherWindow.pack();
launcherWindow.setVisible( true );
new Timer( 5000, new ActionListener() {
public void actionPerformed( ActionEvent e ) {
System.gc();
System.out.println( "Current memory usage after garbage collection: " + getMemoryInfo() );
}
} ).start();
}
} );
}
public static String getMemoryInfo() {
NumberFormat numberFormat = NumberFormat.getNumberInstance();
return "Max heap size is " + numberFormat.format( Runtime.getRuntime().maxMemory() ) + "; free memory is " + numberFormat.format( Runtime.getRuntime().freeMemory() ) + "; total memory is " + numberFormat.format( Runtime.getRuntime().totalMemory() );
}
}