5

Red Hat LinuxでのJavaの問題(IBM JVM 1.4.2 64ビットを使用)を調査しています。誰かが以前にこのエラーメッセージを見て、この問題の回避策があるかどうか知っているかどうか疑問に思っていますか?

ソース:

import sun.misc.Signal;
import sun.misc.SignalHandler;

public class SignalTest extends Thread
{
    private static Signal signal = new Signal("INT");

    private static ShutdownHandler handler = new ShutdownHandler();

    private static class ShutdownHandler implements SignalHandler
    {
        public void handle(Signal sig)
        {
        }
    }

    public static void main(String[] args)
    {
        try
        {
            Signal.handle(signal, handler);
        }
        catch(Throwable e)
        {
            e.printStackTrace();
        }

        try { Thread.sleep(5000); } catch(Exception e) { e.printStackTrace(); }

        System.exit(0);
    }
}

出力:

java.lang.IllegalArgumentException <Signal already used by VM: INT>
java.lang.IllegalArgumentException: Signal already used by VM: INT
at
com.ibm.misc.SignalDispatcher.registerSignal(SignalDispatcher.java:145)
at sun.misc.Signal.handle(Signal.java:199)
at xxx

追加情報:

何かおかしなことに気づきました。失敗する理由は、シェルスクリプト内でプログラムをバックグラウンドプロセスとして実行しているためです。

すなわちsigtest.sh:

#!/bin/bash
java -cp . SignalTest >> sigtest.log 2>&1 &

コマンドラインからプログラムを実行するか、「&」を削除する(つまり、シェルスクリプト内のフォアグラウンドプロセスにする)場合、問題はありません...なぜそうなるのかわかりません。

4

8 に答える 8

3

これは、JVM実装固有の問題である可能性があります。文書化されていない/サポートされていないAPI(sun.misc.Signal/SignalHandler)を使用しているため、APIの動作に関する契約は保証されません。

IBM JVM実装は、SUN JVM実装とは異なる方法で信号処理関連の処理を実行する可能性があるため、この問題が発生する可能性があります。そのため、この特定のユースケースはSUN JVMで機能しますが、IBMJVMでは機能しません。

しかし、以下を試してみてください(私はそれを自分で試すことはできません):

これらのパラメーターの1つまたは2つまたは3つを使用して、JVMを開始することからすべての組み合わせを実行し、可能な値の組み合わせがあります。

  1. -Xrs指定された/指定されていないオプション
  2. /ibm.signalhandling.sigintに設定されたプロパティtruefalse
  3. /ibm.signalhandling.rsに設定されたプロパティtruefalse

(いくつかのエラーダンプでグーグルを介して見つかったプロパティですが、それらに関する特定のドキュメントは見つかりません)

IBM JVMもこの特別なフラグをサポートしているかどうかはわかりませんが、これも追加してみることができます。これは、SUN JVMでは、linux/solarisでのシグナルハンドラーの問題に固有のようです。

-XX:-AllowUserSignalHandlers

または、それがオプションである場合は、ネイティブシグナルハンドラーを使用してみてください。提供されているコードサンプルを確認してください。

特定の問題とは関係ありませんが、JVM信号処理に関するIBMの記事(少し古いですが、ほとんど正しいです)。ネイティブコードシグナルハンドラーのサンプル:

Java信号の処理と終了に関する啓示


SIGINTしかし、IBM JVM実装は、正しく機能するためにそれ自体の処理に依存する可能性があり、したがって、自分自身を処理する機会を決して与えないため、これはすべて役に立たない可能性があると思いSIGINTます。

ところで。説明から旗まで、-Xrsそれが実際にあなたが望むことをするのを妨げるかもしれないことを理解しています。それは言う

がSunのJVMで使用される場合-Xrs、SIGINT、SIGTERM、SIGHUP、およびSIGQUITのシグナルマスクはJVMによって変更されず、これらのシグナルのシグナルハンドラー はインストールされません

または、シグナルのJVMデフォルトアクションのみが実行されないことを意味する場合もあります。または、JVMの実装に依存する可能性があります。

于 2009-07-03T15:00:43.657 に答える
2

とにかくこれに従ってIBMJVMで有効な-Xrsオプションを使用してJVMを起動してみてください。それは衝突を防ぐかもしれません。

編集:あなたの根底にある欲求に応えて、見てください:

Runtime.getRuntime()。addShutdownHook(Thread)

スレッドオブジェクトをサブクラス化すると、シャットダウンの一部として開始されます(これが正常に機能するには、-Xrsを削除してください)。いくつかのこと(Runtimeでhaltを呼び出すなど)はそれが起こらないようにすることができるので、それが起こらない可能性があることに注意する必要があります。

于 2009-06-29T19:39:54.030 に答える
1

Heinz Kabutzが書いたように、キャッチできるシグナルは、実行しているオペレーティングシステムと、場合によってはJVMのバージョンによって異なります。特定のos/jvmの組み合わせで信号を登録できない場合は、運が悪いです。たぶん、os/vm設定を微調整することが役立つかもしれません。

あなたのコメントによると、Yishaiによって提案されたシャットダウンフックを追加することでうまくいくはずです。

于 2009-06-30T21:36:16.283 に答える
0

IBMの代わりに別のJVM実装(SuSE)を使用することで、これを機能させることができました。文書化されていない機能を扱う場合、JVMの動作はあまり一貫していないようです。

于 2009-07-06T15:36:02.310 に答える
0

例外は、VMにSIGINT用のシグナルハンドラーが既に配置されているために発生します。これについて何ができるか/すべきかは、この例外がスローされるコンテキストによって異なります。

于 2009-06-26T18:09:44.400 に答える
0

私は同じコードを試しましたが、それは私のために働きます。ですから、設定に多少の違いがあるのではないかと思います。

追加後

System.out.println("Hello");

ハンドルメッセージに私はそのようなクラスを実行することができます:

z@zolty:/tmp/so$ java SignalTest & sleep 1s && kill -2 $!
[1] 20467
z@zolty:/tmp/so$ Hello
z@zolty:/tmp/so$
z@zolty:/tmp/so$ java SignalTest
[1]+  Done             java SignalTest
于 2009-06-29T19:32:07.337 に答える
0

私も同じ問題を抱えています。kshスクリプトからJavaプログラムを実行します。/ etc/passwdファイルにあるcshプロファイルを持つアカウントでスクリプトを実行した場合

userx:*:7260:20 :: / home / userx:/ usr / bin / csh

スクリプトは正常に実行されます。しかし、shプロファイル以外のアカウントで実行すると、同じエラーが発生します。

したがって、解決策は、UNIXユーザープロファイルをcshに変更することです。

于 2013-12-05T04:01:00.900 に答える
0

Linux上のIBMJVM(64ビット)でもこの問題が発生しました。JVMは、それを呼び出すプロセスのシグナルマスクに敏感であることが判明しました。

> grep Sig /proc/self/status
SigQ:   1/1030663
SigPnd: 0000000000000000
SigBlk: 0000000000000000
SigIgn: 0000000001001006
SigCgt: 0000000000000000

SIGINTのビット(値2)はSigIgnで設定されていることに注意してください。このマスクを使用してIBMJVMを開始すると、SIGINTのハンドラーのインストールを拒否します。SIGINTハンドラーをデフォルトにリセットするPythonラッパーを介してJVMを起動することにより、この問題を回避しました。

#!/usr/bin/env python

import os
import signal
import sys

signal.signal(signal.SIGINT, signal.SIG_DFL)

args = sys.argv[1:]
os.execv(args[0], args)

ラッパーの最初の引数はjavaコマンドで、次にJVMの引数に従います。

于 2016-02-19T14:05:25.490 に答える