web-dev-qa-db-ja.com

Eclipseから起動されたプロセスで実行するシャットダウンフックを取得する方法

アプリケーションにシャットダウンフックがあります(Runtime.getRuntime().addShutdownHookを使用して作成)。ただし、Eclipse内からアプリケーションを起動すると、シャットダウン時にシャットダウンフックが実行されません。

これは、Eclipseが強制終了シグナルに相当するものをプロセスに送信し、シャットダウンフックが実行されないためだと思います(Windowsのtaskkill/FまたはLinuxのkill -pに相当)絶対にわからない。

誰もこれを回避する方法を知っていますか? Windows(Vista)を実行していますが、Windows固有の問題であると感じていますが、よくわかりません。

53
Neil

メインメソッドの最後に次のハックを使用して、問題を回避しました。

if (Boolean.parseBoolean(System.getenv("RUNNING_IN_Eclipse"))) {
    System.out.println("You're using Eclipse; click in this console and " +
            "press ENTER to call System.exit() and run the shutdown routine.");
    try {
        System.in.read();
    } catch (IOException e) {
        e.printStackTrace();
    }
    System.exit(0);
}  
23
Sairam R

まず、アプリケーションは終了していますか、それとも強制的に終了していますか? (停止ボタンを使用して)強制的に終了する場合、この Eclipseバグレポート には、これが機能しない理由に関する詳細が記載されています。

それに失敗すると、これがWindows固有の動作であるということについて正しいかもしれません。 Macを使用しているため、確認できません。申し訳ありません。ただし、次のテストプログラムdoesが期待どおりシャットダウンフックを実行することを伝えることができます。

public class MyShutdownHook
{
    public static void main( String[] args )
    {
        System.out.println( "Entering main." );

        Runtime.getRuntime().addShutdownHook( 
            new Thread(
                new Runnable() {
                    public void run() {
                        System.out.println( "Shutdown hook ran." );
                    }   
                }
            )
        );

        System.out.println( "Exiting main." );
    }
}

Runtime#addShutdownHook のJavadocには、JVMが異常終了した場合、正常に終了しない場合にシャットダウンフックが実行されないことが記載されています。そうは言っても、試してみるべきことがいくつかあります。繰り返しますが、申し訳ありませんが、これらを事前に確認することはできません。ここにはWindowsはありません。 (祝福!)

  • JVMに-Xrsオプションが含まれていないことを確認してください。これには、シャットダウンフックに 副作用 があります。
  • -serverまたは-clientオプションを使用してJVMを起動してみてください。私の経験では、エッジケースの動作は、VM mode。(少なくともMacでは)スレッド化に関して)を選択することで影響を受ける可能性があります。
  • プロファイラーなどでアプリを起動していますか?ネイティブライブラリをロードしていますか?
  • 致命的なエラーが発生し、欠落していますか?たとえば、OutOfMemoryErrorなどですか?
  • EclipseのアプリケーションのRun ConfigurationダイアログからLaunch in backgroundオプションをオン/オフにしてみてください。
  • 最後になりましたが、機会があれば手動でSystem.exit()を呼び出してください。 :)
12
JLR

以下は、Eclipseの外部で実行できるスクリプトで、Eclipseの下で実行できる、強制終了できるプロセスをリストしています。

#!/bin/bash
set -o nounset                              # Treat unset variables as an error

PROCESSES=$(ps axo pid,ppid,command)

# Find Eclipse launcher PID
LAUNCHER_PID=$(echo "$PROCESSES" | grep "/usr/lib/Eclipse/eclipse" |grep -v "launcher"|awk '{print $1}')
echo "Launcher PID $LAUNCHER_PID"

# Find Eclipse PID
Eclipse_PID=$(echo "$PROCESSES" | egrep "[[:digit:]]* $LAUNCHER_PID " | awk '{print $1}')
echo "Eclipse PID $Eclipse_PID"

# Find running Eclipse sub-process PIDs
SUB_PROCESS=$(echo "$PROCESSES" | egrep "[[:digit:]]* $Eclipse_PID " | awk '{print $1}')

# List processes
echo
for PROCESS in $SUB_PROCESS; do
    DRIVER=$(ps --no-headers o pid,ppid,command $PROCESS | awk '{print $NF}')
    echo "$PROCESS $DRIVER"
done

echo "Kill a process using: 'kill -SIGTERM \$PID'"
5
Jason Axelson

Windowsでは、送信する必要のある標準的な方法でJavaアプリケーションを正常に停止するには Ctrl + C それに。これはコンソールアプリでのみ機能しますが、Eclipseはjavaw.exe の代わりに Java.exe。これを解決するには、起動構成の[JRE]タブを開き、[代替JRE:]を選択します。 「Java実行可能ファイル」グループボックスが表示され、代替実行可能ファイル「Java」を入力できます。

ここで、Ctrl-Cを非表示のコンソールを持つプロセスに送信する外部プログラムが必要です。ヒントを見つけました here および here 。プログラムは、目的のプロセスのコンソールに接続し、コンソールイベントを送信します。

#include <stdio.h>
#include <windows.h>

int main(int argc, char* argv[])
{
    if (argc == 2) {
        unsigned pid = 0;
        if (sscanf_s(argv[1], "%u", &pid) == 1) {
            FreeConsole(); // AttachConsole will fail if we don't detach from current console
            if (AttachConsole(pid)) {
                //Disable Ctrl-C handling for our program
                SetConsoleCtrlHandler(NULL, TRUE);
                GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0);
                return 0;
            }
        }
    }

    return 1;
}

テストJavaプログラム:

public class Shuthook {

    public static void main(final String[] args) throws Exception {
        Runtime.getRuntime().addShutdownHook(new Thread() {
            @Override
            public void run() {
                System.out.println("Shutting down...");
            }
        });

        String sPid = ManagementFactory.getRuntimeMXBean().getName();
        sPid = sPid.substring(0, sPid.indexOf('@'));

        System.out.println("pid: " + sPid);
        System.out.println("Sleeping...");
        Thread.sleep(1000000);
    }

}

終了する:

C:\>killsoft.exe 10520

Eclipseでのプログラム出力のテスト:

pid: 10520
Sleeping...
Shutting down...
1
basin

私はこれを修正する方法がわかりませんが、IntelliJは「実行」ダイアログに別のボタンを追加し、シャットダウンフックを呼び出す方法でVMをシャットダウンします。特徴。

1
Javamann

Sairamはここにあります。System.exit(0)を呼び出すことで、Eclipse JVMを終了し、シャットダウンフックの結果を確認できます。

0
Shashank

私は現在、websphereで立ち往生しています。探しているものが見当たりません。ただし、Eclipseには、同じVMでのアプリケーションの起動に関連する実行構成オプションがあります。 JavaアプリケーションをEclipse VMと同じVMで起動することは可能ですか?

しかし、オプションは私の心を滑らせます。

0
guyumu