10

次のコードからの出力は次のとおりです。

java.vendor     Sun Microsystems Inc.
java.version    1.6.0_26
java.runtime.version    1.6.0_26-b03
sun.arch.data.model     32
os.name     Windows XP
os.version  5.1
os.arch     x86
Input selection cancelled by user.
Exception while removing reference: java.lang.InterruptedException
java.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)

次のコードは、私のマシンの例外を示しています。

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class GUI extends JPanel implements ActionListener {

    private final String newline = System.getProperty("line.separator");
    JButton openButton;
    JTextArea log;
    JFileChooser fc;

    public GUI() {
        super(new BorderLayout());

        log = new JTextArea(20,40);
        log.setMargin(new Insets(5,5,5,5));
        log.setEditable(false);

        fc = new JFileChooser();

        openButton = new JButton("Open");
        openButton.addActionListener(this);

        JPanel buttonPanel = new JPanel(); //use FlowLayout
        buttonPanel.add(openButton);

        add(buttonPanel, BorderLayout.NORTH);
        add(new JScrollPane(log));

        showProp("java.vendor");
        showProp("java.version");
        showProp("java.runtime.version");
        showProp("sun.arch.data.model");
        showProp("os.name");
        showProp("os.version");
        showProp("os.arch");
    }

    public void showProp(String name) {
        output(name + " \t" + System.getProperty(name));
    }

    public void output(String msg) {
        log.append(msg + newline);
        log.setCaretPosition(log.getDocument().getLength());
        System.out.println(msg);
    }

    public void actionPerformed(ActionEvent e) {
        //Handle open button action.
        int returnVal = fc.showOpenDialog(GUI.this);

        if (returnVal == JFileChooser.APPROVE_OPTION) {
            //This is where a real application would open the file.
            output(
                "Input File Selected: " +
                fc.getSelectedFile().getName() +
                ".");

        } else {
            output("Input selection cancelled by user.");
        }
        log.setCaretPosition(log.getDocument().getLength());
    }

    /**
     * Create the GUI and show it.  For thread safety,
     * this method should be invoked from the
     * event dispatch thread.
     */
    private static void createAndShowGUI() {
        //Create and set up the window.
        JFrame frame = new JFrame("IDE Output Converter");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //Add content to the window.
        frame.add(new GUI());

        //Display the window.
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        //Schedule a job for the event dispatch thread:
        //creating and showing this application's GUI.
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}

プログラムを実行すると、メインウィンドウが正常に開き、プログラムは正常に動作します。

ただし、次の場合:

  • [ファイルを開くJFileChooser]ボタンを使用してを開きます
  • キャンセルを押してから
  • プログラムを終了します

InterruptedExceptionスローされます。または、ファイルを選択して「開く」とプログラムを終了すると、同じエラーがスローされます。このブログでは、同じことがサンプルコードで説明されています。彼の解決策は、new JFileChooser();できるだけ早く呼び出すことですが、これは効果がありません。

これは1.6.0_26のバグですか?もしそうなら、そのバージョンの回避策はありますか?

それはコードですか?もしそうなら、それを修正する方法は?(他に2つのnull結果があり、そのうちの1つが削除されています。)

4

5 に答える 5

12

これはの小さなバグだと思いsun.awt.Disposerます。

このクラスは、ガベージコレクションされたオブジェクト(主にAWTウィンドウ)のAWTリソースの破棄を処理する「Java2DDisposer」デーモンスレッドを作成します。ほとんどの場合、スレッドは参照キューで新しい使い捨てオブジェクトがガベージコレクションされるのを待ちます。スレッドが中断されると、その例外が明示的に出力されます。

JVMが終了すると、すべてのスレッドが中断されます。JFileChooserの使用法と、JFileChooserによって初期化されたサブシステムの影響を受けていると思われる状況では、この中断後も一部のスレッドが実行される可能性があります。この場合、InterruptedExceptionロックを待機していたため、「Java2DDisposer」スレッドでがスローされます。シャットダウン中にその例外を無視した方がよいでしょう。

回避策として、交換してください

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.addWindowListener(new WindowAdapter() {
    @Override
    public void windowClosed(WindowEvent e) {
        PrintStream nullStream = new PrintStream(new OutputStream() {
            public void write(int b) throws IOException {
            }

            public void write(byte b[]) throws IOException {
            }

            public void write(byte b[], int off, int len) throws IOException {
            }
        });
        System.setErr(nullStream);
        System.setOut(nullStream);
        System.exit(0);
    }
});
于 2011-10-26T09:53:27.563 に答える
4

同様の問題がありました。このスレッドからのアドバイスに従って修正しました

于 2011-10-27T18:39:39.167 に答える
2

ソースのわずかに変更されたバージョン(現在、質問自体の編集として含まれています)の出力は..です。

java.vendor     Sun Microsystems Inc.
java.version    1.6.0_29
java.runtime.version    1.6.0_29-b11
sun.arch.data.model     32
os.name         Windows 7
os.version      6.1
os.arch         x86
Input File Selected: install.ini.
Input selection cancelled by user.
Press any key to continue . . .

あなたの質問から、重要な行は次のようです:

Input selection cancelled by user.

しかし、その後InterruptedException、出力には何も表示されません。

于 2011-10-26T09:41:52.920 に答える
0

ブログ投稿のコードの違いは、JFileChooserのスコープです。ブログ投稿では、オブジェクトはonClickedButton関数内のローカル変数です。この例では、オブジェクトはクラスレベルで定義されています。ローカル変数であると、DisposerスレッドがJFileChooserオブジェクトをクリアするための時間が長くなると思います。

あなたの例のactionPerformedメソッドブロックでファイルチューザーオブジェクトをローカル変数にしたとき、例外は発生しませんでした。私はそれを約10回テストしました。両方とも、eclipseとコマンドラインを介してアプリケーションを実行しました。例外は発生しませんでした。

それでも例外が発生する場合は、GUIのコンストラクターでファイルチューザーオブジェクトを初期化できますが、それを何にも割り当てることはできません。ここでは、重量のあるスイングオブジェクトの初期の初期化と廃棄として機能すると思います。

お役に立てれば。

于 2011-10-27T10:39:15.580 に答える
0

System.gc()JFileChooserを使用して、呼び出しを追加してみてください。この呼び出しで修正されたファイルロックに問題がありました。

于 2011-10-27T11:02:33.600 に答える