1

これは私の最初の質問
なので、非常に奇妙な問題があります。
以下は私の問題です...

テキストをファイルに書き込む非常に単純なメソッドを作成します。
もちろん、私のマシン (XP、4CPU、jdk1.5.0_17[SUN])では問題なく動作しますが、稼働中のサーバー (Linux Accounting240 2.4.20-8smp、4CPU 、 jdk1.5.0_22
[SUN]) でフリーズすることがあります。

kill -3 は機能しません。
ctrl + \ は機能しません。

そのため、スレッド ダンプを表示することはできません。

それはよくフリーズします.. このメソッドで Thread.sleep(XX) を書くだけで、問題は解決しました(?)...
sleep(XX) ブレーク... 今日も Thread.sleep(XX) で発生...

この問題を知っていますか?それについて何か解決策はありますか?ありがとう。:-)

PS
Linux ディストリビューション: Red Hat Linux 3.2.2-5
コマンド: java -cp 。T

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.text.SimpleDateFormat;
import java.util.Date;

public class T {
private BufferedWriter writer = null;

private void log(String log) {
    try {
        if (writer == null) {
            File logFile = new File("test.log");
            writer = new BufferedWriter(new OutputStreamWriter(
                    new FileOutputStream(logFile, true)));
        }
        writer.write(new SimpleDateFormat("[yyyy-MM-dd HH:mm:ss] ")
                .format(new Date()));
        writer.write("[" + log + "]" + "\n");
        writer.flush();

         /*
                         *  this is ad hoc solution ???
                         */
        //Thread.sleep(10);
    } catch (Exception e) {
        e.printStackTrace();
    } finally {         
    }

}

public void test() {
    long startTime = System.currentTimeMillis();

    while (true) {
        log(String.valueOf(System.currentTimeMillis()));
        System.out.println(System.currentTimeMillis());
        try {
            //Thread.sleep((int) (Math.random() * 100));
        } catch (Exception e) {
            break;
        }

        if (System.currentTimeMillis() - startTime > 1000 * 5) {
            break;
        }
    }

    if (writer != null) {
        try {
            writer.close();
        } catch (Exception e) {
        }
    }
    System.out.println("OK");
}

public static void main(String[] args) {
    new T().test();
}
}
4

3 に答える 3

2

JVM が kill -3 に応答しない場合、それはあなたのプログラムではなく、JVM に問題があり、Sun へのバグ レポートが必要です。

2.4.20-8smp カーネルを実行していることに気付きました。これは、現在のオープン ソース Linux ディストリビューションの典型的なカーネルではないため、http://java.sun.com/j2se/1.5.0/system-configurations.htmlを参照して、デプロイしているかどうかを確認することをお勧めします。サポートされている構成に。そうでない場合は、責任者にこれを知らせる必要があります。

于 2009-12-09T08:40:49.273 に答える
0

これは競合状態だと思います。はwhile(true)、Linux 上の VM に継続的に書き込みとフラッシュを強制し、Linux カーネル VM はこれらの呼び出しをインターセプトして書き込みをバッファリングしようとします。これにより、システムコールが完了するのを待っている間、プロセスがスピンループします。同時に、スケジューラによって取得され、別の CPU に割り当てられます (ここで間違っている可能性があります)。新しい CPU はリソースのロックを取得しようとし、すべてがデッドロックになります。

これは、今後の他の問題の兆候である可能性があります。私は提案します:

  • まず、わかりやすくするために、ファイルの作成をlog()メソッドの外に移動します。それがコンストラクターの目的です。

  • 第二に、なぜそのようなファイルに書き込もうとしているのですか? そもそもあなたのプログラム ロジックが理にかなっていると確信していますか? ログ メッセージをコンテナー (ArrayList など) に書き込み、XX 秒ごとにそれを別のスレッドでディスクにダンプしませんか? 現在、ロギング機能をディスク速度に制限しています。これは避けたいと思うかもしれません。

于 2009-12-09T11:13:50.560 に答える
0

最初のステップは、プログラムが「フリーズ」したときのスレッド ダンプを取得することです。これが Java 6 上にある場合、デフォルトで JVisualVM または JConsole に接続し、そこからすべてのスレッドのスタックトレースを取得できます。これは Java 5 であるため、コマンドを使用してスレッド ダンプを取得できるはずですjstack(または、コマンド ライン オプションで JMX を有効にして前述のツールをアタッチすることもできますが、この場合はその価値はないと思います)。いずれの場合も、アプリケーションを起動したコンソールから Ctrl-Break を押すと、環境によってはスレッド ダンプが生成される場合もあります。

これを数秒間隔で数回実行し、スレッド ダンプを比較します。それらが常に同一である場合、アプリケーションがデッドロックしているように見えます。ダンプの一番上の行には、スレッドがブロックされている場所が正確に表示されます (コードのその行を見ると、スレッドがブロックされているリソースについて非常に良い手がかりが得られます)。

一方、スレッドダンプが時々変化する場合、プログラムは厳密にはデッドロックされていませんが、無限ループで実行されているように見えます.おそらくループ条件の1つが適切に宣言されていないため、スレッドが終了しないか、そのようなものです. . 繰り返しますが、一連のスレッド ダンプを見て、各スレッドがループしているコードの領域を確認します。これにより、決して終了条件に評価されないループ条件がわかります。

この分析で問題が明らかでない場合は、上記のコードをデバッグするのに役立つため、ダンプを投稿してください。

于 2009-12-09T09:18:16.520 に答える