Tuesday, August 09, 2011

Java and late file dialog instantiation

Interesting: Java provides a JFileChooser to provide a file dialog for the
Swing UI framework. Typically I create objects when I need them - so
it was clear to me that I instantiate the class in this example only when
a button is clicked (most other examples on the web instantiate the dialog with the main window):



package foo;

import java.awt.BorderLayout;

public class TestWindow extends JFrame {

private JPanel contentPane;

public static void main(String[] args) {

EventQueue.invokeLater(new Runnable() {
public void run() {
try {
TestWindow frame = new TestWindow();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}

/**
* Create the frame.
*/
public TestWindow() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setLayout(new BorderLayout(0, 0));
setContentPane(contentPane);

JButton btnOpenFileDialog = new JButton("Open file dialog");
btnOpenFileDialog.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
onClickedButton();
}
});
contentPane.add(btnOpenFileDialog, BorderLayout.CENTER);
}

protected void onClickedButton() {
JFileChooser fileChooser = new JFileChooser();
fileChooser.showOpenDialog(this); // open modal on main window
}
}



When you run this simple application within Eclipse, click the "Open" button and
close the file dialog via "Cancel" you will notice that an
exception will appear on stdout as soon as you close the main window:



Exception while removing reference: java.lang.InterruptedExceptionjava.lang.InterruptedException
at java.lang.Object.wait(Native Method)
at java.lang.ref.ReferenceQueue.remove(Unknown Source)
at java.lang.ref.ReferenceQueue.remove(Unknown Source)
at sun.java2d.Disposer.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)


So the app is not closed correctly and error free.

And I found a workaround, the exception will not appear if you
create an instance of JFileDialog as early as possible in your app:



public static void main(String[] args) {
new JFileChooser();
...



Since it is not referenced this instance becomes directly a victim of
the next GC - but anyway creating an instance of JFileChooser right at the beginning seem
to trigger an initialization that is required to prevent the above problem.

Thought I would share this if others run into the same problem. Another possibility is to use a better system.

1 comment:

Garry Knight said...

I found that if I did a System.gc() just after getting the JFileChooser.CANCEL_OPTION and before returning null to my calling method, then I wouldn't get the "Exception while removing reference" message. I should add that in my case I got the message but didn't even get a stacktrace.