2011-02-01 4 views
9

私の驚きと恐怖に、私は使用しているライブラリのSystem.exit(1);という行にちょうど遭遇しました。私は図書館の著者に連絡して何が得られるか尋ねるつもりですが、図書館が私のコードを殺すのを防ぐための方法はありますか?(さらに、私のコードを使ってアプリケーションを殺すのですか?ライブラリで終了指示をキャッチ

おそらく何とか図書館にSecurityExceptionを投げ入れるように強制すると、exit(int)が投げられることがありますか?

答えて

13

私が知っている唯一の方法があり、それはSecurityManagerをコードしてSystem.exitの使用を許可しないことです。

public class MySecurityMgr extends SecurityManager { 
    ... 

    @Override 
    public void checkExit(int status) { 
      throw new RuntimeException(Integer.toString(status)); 
    } 
} 
4

はい、あなたはcheckExitをオーバーライドするSecurityManagerをインストールすることができます。

これは、テスト済みのコードが0で終了しないことを確認するコードをunittestingする場合に特に便利であることがわかりました。

SecurityExceptionが正常に長寿命の基本スレッドを強制終了しても、これは役に立ちません。

4

私はあなたの唯一の選択肢(濡れたタオルで書いた人が彼の書いたものを書き換えるまでの間、短くない)は、ライブラリのバイトコードを変更することだと思います。

かなりのアプローチは、ライブラリをロードするときに読み込み時に織り込む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について他の回答を見てきましたし、私はそれはおそらく移動するための方法です同意するが、私は残しておきます代わりに私の答えはここに。

3

はいセキュリティマネージャトリックを行うことができます

// 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); 
} 
関連する問題