私の驚きと恐怖に、私は使用しているライブラリのSystem.exit(1);
という行にちょうど遭遇しました。私は図書館の著者に連絡して何が得られるか尋ねるつもりですが、図書館が私のコードを殺すのを防ぐための方法はありますか?(さらに、私のコードを使ってアプリケーションを殺すのですか?ライブラリで終了指示をキャッチ
おそらく何とか図書館にSecurityException
を投げ入れるように強制すると、exit(int)
が投げられることがありますか?
私の驚きと恐怖に、私は使用しているライブラリのSystem.exit(1);
という行にちょうど遭遇しました。私は図書館の著者に連絡して何が得られるか尋ねるつもりですが、図書館が私のコードを殺すのを防ぐための方法はありますか?(さらに、私のコードを使ってアプリケーションを殺すのですか?ライブラリで終了指示をキャッチ
おそらく何とか図書館にSecurityException
を投げ入れるように強制すると、exit(int)
が投げられることがありますか?
私が知っている唯一の方法があり、それはSecurityManager
をコードしてSystem.exitの使用を許可しないことです。
public class MySecurityMgr extends SecurityManager {
...
@Override
public void checkExit(int status) {
throw new RuntimeException(Integer.toString(status));
}
}
はい、あなたはcheckExit
をオーバーライドするSecurityManager
をインストールすることができます。
これは、テスト済みのコードが0で終了しないことを確認するコードをunittestingする場合に特に便利であることがわかりました。
SecurityException
が正常に長寿命の基本スレッドを強制終了しても、これは役に立ちません。
私はあなたの唯一の選択肢(濡れたタオルで書いた人が彼の書いたものを書き換えるまでの間、短くない)は、ライブラリのバイトコードを変更することだと思います。
かなりのアプローチは、ライブラリをロードするときに読み込み時に織り込むAspectJを使用することです。醜いオプションは、asmのようなツールを使用してメソッド呼び出しを削除または変更することです。
はここSystem.exit()
への呼び出しを偏向AspectJのアスペクトです:
public aspect SystemExitEvader{
pointcut systemExitCall() : call(* java.lang.System.exit(*));
void around() : systemExitCall(){
System.out.println("Call to System.exit() attempted");
// note: there is no call to proceed()
}
}
OK、私はSecurityManagersについて他の回答を見てきましたし、私はそれはおそらく移動するための方法です同意するが、私は残しておきます代わりに私の答えはここに。
はいセキュリティマネージャトリックを行うことができます
// install security manager to avoid System.exit() call from lib
SecurityManager previousSecurityManager = System.getSecurityManager();
final SecurityManager securityManager = new SecurityManager() {
@Override public void checkPermission(final Permission permission) {
if (permission.getName() != null && permission.getName().startsWith("exitVM")) {
throw new SecurityException();
}
}
};
System.setSecurityManager(securityManager);
try {
// Call here your lib code
} catch (SecurityException e) {
// Say hi to your favorite creator of closed source software that includes System.exit() in his code.
} finally {
System.setSecurityManager(previousSecurityManager);
}