外部のクラスのmain()を呼んだりしてみたところ、System.exit()されて後続の処理をキャンセルされてしまいました。それでは困るので、セキュリティマネージャーの力を借りてみました。
// 現在のセキュリティマネージャを取得
final SecurityManager originalManager = System.getSecurityManager();
// 新しいセキュリティマネージャを作る
System.setSecurityManager(new SecurityManager() {
// exitされたくない
public void checkExit(int code){
throw new MyExitException(code, "can not exit.");
}
// 他の操作は元のセキュリティマネージャにお願い
public void checkPermission(Permission perm){
if(originalManager != null)
originalManager.checkPermission(perm);
}
// 他の操作は元のセキュリティマネージャにお願い
public void checkPermission(Permission perm, Object obj) {
if(originalManager != null)
originalManager.checkPermission(perm, obj);
}
});
Exception occured = null;
try{
// 外部のメインルーチンを呼ぶ
Outerclass.main(new String[] {"arg1", "arg2"});
}catch(MyExitException mee){
// exitされた
if(mee.getCode() != 0) occured = mee;
// exitの戻り値が正常終了( = 0 )ならNOP
}catch(Exception e){
// 例外が投げられた
occured = e;
}finally{
// セキュリティマネージャを戻す
System.setSecurityManager(originalManager);
}
if(occured != null){
/* 思う存分エラー処理 */
...
}checkPermission()しか上書きしてない辺りがひじょーに自信ないので、クリティカルな場面ではjavaのセキュリティについてよく調べてから使ったほうが吉です。後、SecurityManagerの上書きができない状態になってることもあるので、そのときは諦めましょうorz。*1
いらないと思うけど、内部クラスのMyExitExceptionも載せときます。
static private class MyExitException extends RuntimeException{
private final int code;
MyExitException(int code){
this(code, null);
}
MyExitException(int code, String message){
this(code, message, null);
}
MyExitException(int code, String message, Throwable th){
super(message, th);
this.code = code;
};
int getCode(){
return code;
}
}*1:後、Errorは潔く諦めてますが、それもなんとかしたければThrowableで。